home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / siod / siod-v2.8vm < prev   
Encoding:
Text File  |  1993-07-17  |  126.6 KB  |  4,490 lines

  1. $! ................... Cut between dotted lines and save. ...................
  2. $!...........................................................................
  3. $! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989.
  4. $!
  5. $! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
  6. $! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
  7. $!
  8. $! To unpack, simply save, concatinate all parts into one file and
  9. $! execute (@) that file.
  10. $!
  11. $! This archive was created by user GJC
  12. $! on 25-JUN-1992 12:45:44.43.
  13. $!
  14. $! It contains the following 17 files:
  15. $!        MAKEFILE.
  16. $!        README.
  17. $!        SIOD.1
  18. $!        SIOD.C
  19. $!        SIOD.DOC
  20. $!        SIOD.H
  21. $!        SIOD.SCM
  22. $!        SLIB.C
  23. $!        SIOD.TIM
  24. $!        MAKEFILE.COM
  25. $!        PRATT.SCM
  26. $!        DESCRIP.MMS
  27. $!        SIOD.OPT
  28. $!        SHAR.DB
  29. $!        SIODP.H
  30. $!        SLIBA.C
  31. $!        SIODM.C
  32. $!
  33. $!============================================================================
  34. $ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
  35. $ VERSION = F$GETSYI( "VERSION" )
  36. $ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
  37. $ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
  38.     "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher."
  39. $ EXIT 44 ! SS$_ABORT
  40. $VERSION_OK:
  41. $ GOTO START
  42. $!
  43. $UNPACK_FILE:
  44. $ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
  45. $ DEFINE/USER_MODE SYS$OUTPUT NL:
  46. $ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
  47.     VMS_SHARE_DUMMY.DUMMY
  48. b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
  49. ; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
  50. , b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors 
  51. := 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN 
  52. & "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
  53. ( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail 
  54. & LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP
  55. ; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK
  56. ( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 )
  57. ; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip 
  58. <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF
  59. ; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT )
  60. ; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip 
  61. := MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip 
  62. <> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET )
  63. ; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) 
  64. ); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
  65. ; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE
  66. ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1
  67. ; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line 
  68. <> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF
  69. ; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors 
  70. := i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
  71. ( "The following line could not be unpacked properly:" ); SPLIT_LINE
  72. ; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL
  73. ( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH
  74. ( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 
  75. ); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP
  76. ; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION
  77. ( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO
  78. ( "The following !UL errors were detected while unpacking !AS", i_errors
  79. , s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" )
  80. ; ENDIF; EXIT; 
  81. $ DELETE VMS_SHARE_DUMMY.DUMMY;*
  82. $ CHECKSUM 'FILE_IS
  83. $ WRITE SYS$OUTPUT " CHECKSUM ", -
  84.   F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." )
  85. $ RETURN
  86. $!
  87. $START: 
  88. $ FILE_IS = "MAKEFILE."
  89. $ CHECKSUM_IS = 1148977636
  90. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  91. X# If cc doesn't work here, try changing cc to gcc (GNU C)
  92. X`009    CC=cc
  93. X`009    CFLAGS= -O
  94. X
  95. Xsiod:`009siod.o slib.o sliba.o
  96. X`009$(CC) -o siod siod.o slib.o sliba.o
  97. Xsiod.o: siod.c siod.h
  98. X`009$(CC) $(CFLAGS) -c siod.c
  99. Xslib.o:`009slib.c siod.h siodp.h
  100. X`009$(CC) $(CFLAGS) -c slib.c
  101. Xsliba.o:`009sliba.c siod.h siodp.h
  102. X`009$(CC) $(CFLAGS) -c sliba.c
  103. $ GOSUB UNPACK_FILE
  104.  
  105. $ FILE_IS = "README."
  106. $ CHECKSUM_IS = 172181293
  107. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  108. XThis is version 2.8 of Siod, Scheme In One Defun.
  109. X
  110. XIt is a very small implementation of the Scheme programming language.
  111. X
  112. XGeorge Carrette, APRIL 3, 1992. gjc@mitech.com, gjc@paradigm.com.
  113. X
  114. XSee siod.doc and the source file slib.c for more information.
  115. X
  116. XThe files slib.c and sliba.c may serve as a subroutine library to add
  117. Xscheme interpreter functionality to any existing program.
  118. X
  119. XEven though this is small, with an executable size of
  120. X38kbytes on VAX/VMS, 50kbytes on Mac, for example,`032
  121. Xthe implementation supports some advanced features such
  122. Xas arrays, hash tables, and fast/binary data saving and restoring.
  123. X
  124. $ GOSUB UNPACK_FILE
  125.  
  126. $ FILE_IS = "SIOD.1"
  127. $ CHECKSUM_IS = 1881288929
  128. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  129. X.TH SIOD 1C LOCAL`032
  130. X.SH NAME
  131. Xsiod \- small scheme interpreter (Scheme In One Defun).
  132. X.SH SYNOPSIS
  133. X.B siod
  134. X[-hXXXXX] [-iXXXXX] [-gX] [-oXXXXX] [-nXXXX]
  135. X.SH DESCRIPTION
  136. X.I Siod
  137. Xis a very small scheme interpreter which can be used for calculations
  138. Xor included as a command interpreter or extension/macro language in other
  139. Xapplications. See the documentation for interfacing requirements and how to
  140. Xadd user-defined data types.
  141. X
  142. X.RE
  143. X.SS COMMAND LINE OPTIONS
  144. X.TP 8
  145. X.BI \-h "XXXXX"
  146. XThe
  147. X.I XXXXX
  148. Xshould be an integer, specifying the number of cons cells to
  149. Xallocate in the heap. The default is 5000.
  150. X.TP
  151. X.BI \-i "XXXXX"
  152. XThe`032
  153. X.I XXXXX
  154. Xshould be the name of an init file to load before going into
  155. Xthe read/eval/print loop.
  156. X.TP
  157. X.BI \-g "X"
  158. XThe
  159. X.I X
  160. Xis 1 for a stop and copy garbage collector (the default), 0 for a mark
  161. Xand sweep one.
  162. X.TP
  163. X.BI \-o "XXXXX"
  164. XThe
  165. X.I XXXXX
  166. Xshould be an integer, specifying the size of the obarray (symbol hash table)
  167. Xto use. Defaults to 100. Each array element is a list of symbols.
  168. X.TP
  169. X.BI \-n "XXXXX"
  170. XThe
  171. X.I XXXXX
  172. Xshould be an integer, specifying the number of pre-cons numbers
  173. Xto create. The default is 100.
  174. X.TP
  175. X.BI \-s "XXXXX"
  176. XThe
  177. X.I XXXXX
  178. Xshould be an integer, specifying the number of bytes of recursion
  179. Xon the machine (C-call frame) stack to allow. This may be changed
  180. Xwhile the programming is running, and is mainly a convenience for
  181. Xdetecting defects in programs.
  182. X
  183. X.SH FILES
  184. Xsiod.h siod.doc siod.scm slib.c sliba.c siod.c siodp.h
  185. X.PD
  186. X.SH SEE ALSO
  187. X.I Structure and Interpretation of Computer Programs
  188. X, by Ableson and Sussman, MIT Press.
  189. X.SH DIAGNOSTICS
  190. XError messages may also set the variable errobj to the offending object.
  191. X.SH BUGS
  192. XWith -g1 it does not GC during EVAL, only before each READ/EVAL/PRINT cycle.
  193. VIt does GC during EVAL with -g0, but that code may not run without modificati
  194. Xon
  195. Xon all architectures.
  196. X.SH VERSION
  197. XCurrent version is 2.8, 3-APR-92, by George Carrette. GJC\@PARADIGM.COM
  198. $ GOSUB UNPACK_FILE
  199.  
  200. $ FILE_IS = "SIOD.C"
  201. $ CHECKSUM_IS = 1481995165
  202. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  203. X/* Scheme In One Defun, but in C this time.
  204. X`032
  205. X *                    COPYRIGHT (c) 1988-1992 BY                            *
  206. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  207. X *        See the source file SLIB.C for more information.                  *
  208. X
  209. X*/
  210. X
  211. X/*
  212. X
  213. Xgjc@paradigm.com
  214. X
  215. XParadigm Associates Inc          Phone: 617-492-6079
  216. X29 Putnam Ave, Suite 6
  217. XCambridge, MA 02138
  218. X
  219. XAn example main-program call with some customized subrs.
  220. X
  221. X  */
  222. X
  223. X#include <stdio.h>
  224. X#ifdef THINK_C
  225. X#include <console.h>
  226. X#endif
  227. X
  228. X#include "siod.h"
  229. X
  230. XLISP my_one;
  231. XLISP my_two;
  232. X
  233. XLISP cfib(LISP x);
  234. X
  235. X#ifdef VMS
  236. XLISP vms_debug(LISP cmd);
  237. X#endif
  238. X
  239. Xint main(int argc,char **argv)
  240. X`123print_welcome();
  241. X#ifdef THINK_C
  242. X argc = ccommand(&argv);
  243. X#endif
  244. X process_cla(argc,argv,1);
  245. X print_hs_1();
  246. X init_storage();
  247. X init_subrs();
  248. X my_one = flocons((double) 1.0);
  249. X my_two = flocons((double) 2.0);
  250. X gc_protect(&my_one);
  251. X gc_protect(&my_two);
  252. X init_subr("cfib",tc_subr_1,cfib);
  253. X#ifdef VMS
  254. X init_subr("vms-debug",tc_subr_1,vms_debug);
  255. X#endif
  256. X repl_driver(1,1);
  257. X printf("EXIT\n");`125
  258. X
  259. X/* This is cfib, (compiled fib). Test to see what the overhead
  260. X   of interpretation actually is in a given implementation benchmark
  261. X   standard-fib against cfib.
  262. X
  263. X   (define (standard-fib x)
  264. X     (if (< x 2)
  265. X         x
  266. X         (+ (standard-fib (- x 1))
  267. X`009    (standard-fib (- x 2))))) `032
  268. X
  269. X*/
  270. X
  271. XLISP cfib(LISP x)
  272. X`123if NNULLP(lessp(x,my_two))
  273. X   return(x);
  274. X else
  275. X   return(plus(cfib(difference(x,my_one)),
  276. X`009       cfib(difference(x,my_two))));`125
  277. X
  278. X#ifdef VMS
  279. X
  280. X#include <ssdef.h>
  281. X#include <descrip.h>
  282. X
  283. XLISP vms_debug(arg)
  284. X     LISP arg;
  285. X`123unsigned char arg1[257];
  286. X char *data;
  287. X if NULLP(arg)
  288. X   lib$signal(SS$_DEBUG,0);
  289. X else
  290. X   `123data = get_c_string(arg);
  291. X    arg1[0] = strlen(data);
  292. X    memcpy(&arg1[1],data,arg1[0]);
  293. X    lib$signal(SS$_DEBUG,1,arg1);`125
  294. X return(NIL);`125
  295. X
  296. X#endif
  297. $ GOSUB UNPACK_FILE
  298.  
  299. $ FILE_IS = "SIOD.DOC"
  300. $ CHECKSUM_IS = 657114964
  301. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  302. X *                   COPYRIGHT (c) 1988-1992 BY                             *
  303. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  304. X *        See the source file SLIB.C for more information.                  *
  305. X
  306. XDocumentation for Release 2.7 17-MAR-92, George Carrette
  307. X
  308. X[Release Notes:]
  309. X
  310. X1.4 This release is functionally the same as release 1.3 but has been
  311. Xremodularized in response to people who have been encorporating SIOD
  312. Xas an interpreted extension language in other systems.
  313. X
  314. X1.5 Added the -g flag to enable mark-and-sweep garbage collection.
  315. X    The default is stop-and-copy.
  316. X
  317. X2.0 Set_Repl_Hooks, catch & throw.`032
  318. X
  319. X2.1 Additions to SIOD.SCM: Backquote, cond.
  320. X
  321. X2.2 User Type extension. Read-Macros. (From C-programmer level).
  322. X
  323. X2.3 save-forms. load with argument t, comment character, faster intern.
  324. X    -o flag gives obarray size. default 100.
  325. X
  326. X2.4 speed up arithmetic and the evaluator. fixes to siod.scm. no_interrupt
  327. X    around calls to C I/O. gen_readr.
  328. X
  329. X2.5 numeric arrays in siod.c
  330. X
  331. X2.6 remodularize .h files, procedure prototypes. gc, eval, print hooks
  332. X    now table-driven.
  333. X
  334. X2.7 hash tables, fasload.
  335. X
  336. Xgjc@paradigm.com
  337. XGeorge Carrette
  338. X
  339. X  `032
  340. XParadigm Associates Inc          Phone: 617-492-6079
  341. X29 Putnam Ave, Suite 6
  342. XCambridge, MA 02138
  343. X
  344. X[Files:]
  345. X
  346. X siod.h    Declarations`032
  347. X siodp.h   private declarations.
  348. X slib.c    scheme library.
  349. X siod.c    a main program.
  350. X siod.scm  Some scheme code
  351. X pratt.scm A pratt-parser in scheme.
  352. X
  353. X
  354. X[Motivation:]
  355. X
  356. XThe most obvious thing one should notice is that this lisp implementation`032
  357. Xis extremely small. For example, the resulting binary executable file`032
  358. Xon a VAX/VMS system with /notraceback/nodebug is 17 kilo-bytes.
  359. X
  360. XSmall enough to understand, the source file slib.c is 30 kilo-bytes.
  361. X
  362. XSmall enough to include in the smallest applications which require
  363. Xcommand interpreters or extension languages.
  364. X
  365. XWe also want to be able to run code from the book "Structure and
  366. XInterpretation of Computer Programs."`032
  367. X
  368. XTechniques used will be familiar to most lisp implementors.  Having
  369. Xobjects be all the same size, and having only two statically allocated
  370. Xspaces simplifies and speeds up both consing and gc considerably.  the
  371. XMSUBR hack allows for a modular implementation of tail recursion, `009
  372. Xan extension of the FSUBR that is, as far as I know, original.
  373. XThe optional mark and sweep garbage collector may be selected at runtime.
  374. X
  375. XError handling is rather crude. A topic taken with machine fault,
  376. Xexception handling, tracing, debugging, and state recovery which we
  377. Xcould cover in detail, but is clearly beyond the scope of this
  378. Ximplementation. Suffice it to say that if you have a good symbolic
  379. Xdebugger you can set a break point at "err" and observe in detail all
  380. Xthe arguments and local variables of the procedures in question, since
  381. Xthere is no casting of data types. For example, if X is an offending
  382. Xor interesting object then examining X->type will give you the type,
  383. Xand X->storage_as.cons will show the car and the cdr.
  384. X
  385. X[Invocation:]
  386. X
  387. Xsiod [-hXXXXX] [-iXXXXX] [-gX] [-oXXXXX] [-nXXXXX] [-sXXXXX]
  388. X -h where XXXXX is an integer, to specify the heap size, in obj cells,
  389. X -i where XXXXX is a filename to load before going into the repl loop.
  390. X -g where X = 1 for stop-and-copy GC, X = 0 for mark-and-sweep.
  391. X -o where XXXXX is the size of the symbol hash table to use, default 100.
  392. X -n where XXXXX is the number of preconsed/interned non-negative numbers.
  393. X -s where XXXXX is the number of bytes of machine recursion stack.
  394. X
  395. X  Example:
  396. X   siod -isiod.scm -h100000
  397. X
  398. X[Garbage Collection:]
  399. X
  400. XThere are two storage management techniques which may be chosen at runtime
  401. Xby specifying the -g argument flag.`032
  402. X
  403. X -g1 (the default) is stop-and-copy. This is the simplest and most
  404. X     portable implementation. GC is only done at toplevel.
  405. X -g0 is mark-and-sweep. GC is done at any time, required or requested.
  406. X     However, the implementation is not as portable.
  407. X
  408. XDiscussion of stop-and-copy follows:
  409. X
  410. XAs one can see from the source, garbage collection is really quite an easy
  411. Xthing. The procedure gc_relocate is about 25 lines of code, and
  412. Xscan_newspace is about 15.
  413. X
  414. XThe real tricks in handling garbage collection are (in a copying gc):
  415. X (1) keeping track of locations containing objects
  416. X (2) parsing the heap (in the space scanning)
  417. X
  418. XThe procedure gc_protect is called once (e.g. at startup) on each
  419. X"global" location which will contain a lisp object.
  420. X
  421. XThat leaves the stack. Now, if we had chosen not to use the argument
  422. Xand return-value passing mechanism provided by the C-language
  423. Ximplementation, (also known as the "machine stack" and "machine
  424. Xprocedure calling mechanism) this lisp would be larger, slower, and
  425. Xrather more difficult to read and understand. Furthermore it would be
  426. Xconsiderably more painful to *add* functionality in the way of SUBR's
  427. Xto the implementation.
  428. X
  429. XAside from writing a very machine and compiler specific assembling language
  430. Xroutine for each C-language implementation, embodying assumptions about
  431. Xthe placement choices for arguments and local values, etc, we
  432. Xare left with the following limitation: "YOU CAN GC ONLY AT TOP-LEVEL"
  433. X
  434. XHowever, this fits in perfectly with the programming style imposed in
  435. Xmany user interface implementations including the MIT X-Windows Toolkit.
  436. XIn the X Toolkit, a callback or work procedure is not supposed to spend
  437. Xmuch time implementing the action. Therefore it cannot have allocated
  438. Xmuch storage, and the callback trampoline mechanism can post a work
  439. Xprocedure to call the garbage collector when needed.
  440. X
  441. XOur simple object format makes parsing the heap rather trivial.
  442. XIn more complex situations one ends up requiring object headers or markers
  443. Xof some kind to keep track of the actual storage lengths of objects
  444. Xand what components of objects are lisp pointers.
  445. X
  446. XBecause of the usefulness of strings, they were added by default into
  447. XSIOD 2.6. The implementation requires a hook that calls the C library
  448. Xmemory free procedure when an object is in oldspace and never
  449. Xgot relocated to newspace. Obviously this slows down the mark-and-sweep
  450. XGC, and removes one of the usual advantages it has over mark-and-sweep.
  451. X
  452. XDiscussion of mark-and-sweep follows:
  453. X
  454. XIn a mark-and-sweep GC the objects are not relocated. Instead
  455. Xone only has to LOOK at objects which are referenced by the argument
  456. Xframes and local variables of the underlying (in this case C-coded)
  457. Ximplementation procedures. If a pointer "LOOKS" like it is a valid
  458. Xlisp object (see the procedure mark_locations_array) then it may be marked,
  459. Xand the objects it points to may be marked, as being in-use storage which
  460. Xis not linked into the freelist in the gc_sweep phase.
  461. X
  462. XAnother advantage of the mark_and_sweep storage management technique is
  463. Xthat only one heap is required.
  464. X
  465. XThis main disadvantages are:
  466. X(1) start-up cost to initially link freelist.
  467. X    (can be avoided by more general but slower NEWCELL code).
  468. X(2) does not COMPACT or LOCALIZE the use of storage. This is poor engineering
  469. X    practice in a virtual memory environment.
  470. V(2) the entire heap must be looked at, not just the parts with useful storage
  471. X.
  472. X
  473. XIn general, mark-and-sweep is slower in that it has to look at more
  474. Xmemory locations for a given heap size, however the heap size can
  475. Xbe smaller for a given problem being solved. More complex analysis
  476. Xis required when READ-ONLY, STATIC, storage spaces are considered.
  477. XAdditionally the most sophisticated stop-and-copy storage management
  478. Xtechniques take into account considerations of object usage temporality.
  479. X
  480. XThe technique assumes that all machine registers the GC needs to
  481. Xlook at will be saved by a setjmp call into the save_regs_gc_mark data.
  482. X
  483. X[Compilation:]
  484. X
  485. XThis code (version 2.7) has been compiled and run under the following:
  486. X- SUN-IV,      GCC (GNU C)
  487. X- VAX/VMS,     VAXC
  488. X- MacIntosh,   THINK C 5.0
  489. X
  490. XEarlier versions were compiled and run on the AMIGA, Encore, and 4.3BSD.
  491. XThere are reports that the code will also compile and run under MS-DOS.
  492. X
  493. XOn all unix machines use (with floating-point flags as needed)
  494. X `032
  495. X  %cc -O -c siod.c
  496. X  %cc -O -c slib.c
  497. X  %cc -O -c sliba.c
  498. X  %cc -o siod siod.o slib.o sliba.o
  499. X
  500. XIf cc doesn't work, try gcc (GNU C, Free Software Foundation, Cambridge MA).
  501. X
  502. Xon VAX/VMS:
  503. X
  504. X  $ cc siod
  505. X  $ cc slib
  506. X  $ cc sliba
  507. X  $ link siod,slib,sliba,sys$input:/opt
  508. X  sys$library:vaxcrtl/share
  509. X  $ siod == "$" + F$ENV("DEFAULT") + "SIOD"
  510. X
  511. Xon AMIGA 500, ignore warning messages about return value mismatches,
  512. X  %lc siod.c
  513. X  %lc slib.c
  514. X  %lc sliba.c
  515. V  %blink lib:c.o,siod.o,slib.o,sliba.o to siod lib lib:lcm.lib,lib:lc.lib,lib
  516. X:amiga.lib
  517. X
  518. Xin THINK C.
  519. X  The siod project must include siod.c,slib.c,slib.c,sliba.c,siodm.c, ANSI.
  520. X  The compilation option "require prototypes" should be used.
  521. X
  522. X[System:]
  523. X`032
  524. XThe interrupts called SIGINT and SIGFPE by the C runtime system are
  525. Xhandled by invoking the lisp error procedure. SIGINT is usually caused
  526. Vby the CONTROL-C character and SIGFPE by floating point overflow or underflow
  527. X.
  528. X
  529. X[Syntax:]
  530. X
  531. XThe only special characters are the parenthesis and single quote.
  532. XEverything else, besides whitespace of course, will make up a regular token.
  533. XThese tokens are either symbols or numbers depending on what they look like.
  534. XDotted-list notation is not supported on input, only on output.
  535. X
  536. X[Special forms:]
  537. X
  538. XThe CAR of a list is evaluated first, if the value is a SUBR of type 9 or 10
  539. Xthen it is a special form.
  540. X
  541. X(define symbol value) is presently like (set! symbol value).
  542. X
  543. X(define (f . arglist) . body) ==> (define f (lambda arglist . body))
  544. X
  545. X(lambda arglist . body) Returns a closure.
  546. X
  547. X(if pred val1 val2) If pred evaluates to () then val2 is evaluated else val1.
  548. X
  549. X(begin . body) Each form in body is evaluated with the result of the last
  550. Xreturned.
  551. X
  552. X(set! symbol value) Evaluates value and sets the local or global value of
  553. Xthe symbol.
  554. X
  555. X(or x1 x2 x3 ...) Returns the first Xn such that Xn evaluated non-().
  556. X
  557. X(and x1 x2 x3 ...) Keeps evaluating Xj until one returns (), or Xn.
  558. X
  559. X(quote form). Input syntax 'form, returns form without evaluation.
  560. X
  561. X(let pairlist . body) Each element in pairlist is (variable value).
  562. XEvaluates each value then sets of new bindings for each of the variables,
  563. Xthen evaluates the body like the body of a progn. This is actually
  564. Ximplemented as a macro turning into a let-internal form.
  565. X
  566. X(the-environment) Returns the current lexical environment.
  567. X
  568. X[Macro Special forms:]
  569. X
  570. XIf the CAR of a list evaluates to a symbol then the value of that symbol
  571. Xis called on a single argument, the original form. The result of this
  572. Xapplication is a new form which is recursively evaluated.
  573. X
  574. X[Built-In functions:]
  575. X
  576. XThese are all SUBR's of type 4,5,6,7, taking from 0 to 3 arguments
  577. Xwith extra arguments ignored, (not even evaluated!) and arguments not
  578. Xgiven defaulting to (). SUBR's of type 8 are lexprs, receiving a list
  579. Xof arguments. Order of evaluation of arguments will depend on the
  580. Ximplementation choice of your system C compiler.
  581. X
  582. Xconsp cons car cdr set-car! set-cdr!
  583. X
  584. Xnumber? + - * / < > eqv?
  585. XThe arithmetic functions all take two arguments.
  586. X
  587. Xeq?, pointer objective identity. (Use eqv? for numbers.)
  588. X
  589. Xsymbolconc, takes symbols as arguments and appends them.`032
  590. X
  591. Xsymbol?
  592. X
  593. Xsymbol-bound? takes an optional environment structure.
  594. Xsymbol-value also takes optional env.
  595. Xset-symbol-value also takes optional env.
  596. X
  597. Xenv-lookup takes a symbol and an environment structure. If it returns
  598. Xnon-nil the CAR will be the value of the symbol.
  599. X
  600. Xassq
  601. X
  602. Xread,print
  603. X
  604. Xeval, takes a second argument, an environment.
  605. X
  606. Xcopy-list. Copies the top level conses in a list.
  607. X
  608. Xoblist, returns a copy of the list of the symbols that have been interned.
  609. X
  610. Xgc-status, prints out the status of garbage collection services, the
  611. Xnumber of cells allocated and the number of cells free. If given
  612. Xa () argument turns gc services off, if non-() turns gc services on.
  613. XIn mark-and-sweep storage management mode the argument only turns on
  614. Xand off verbosity of GC messages.
  615. X
  616. Xgc, does a mark-and-sweep garbage collection. If called with argument nil
  617. Xdoes not print gc messages during the gc.
  618. X
  619. Xload, given a filename (which must be a symbol, there are no strings)
  620. Xwill read/eval all the forms in that file. An optional second argument,
  621. Xif T causes returning of the forms in the file instead of evaluating them.
  622. X
  623. Xsave-forms, given a filename and a list of forms, prints the forms to the
  624. Xfile. 3rd argument is optional, 'a to open the file in append mode.
  625. X
  626. Xquit, will exit back to the operating system.
  627. X
  628. Xerror, takes a symbol as its first argument, prints the pname of this
  629. Xas an error message. The second argument (optional) is an offensive
  630. Xobject. The global variable errobj gets set to this object for later
  631. Xobservation.
  632. X
  633. Xnull?, not. are the same thing.
  634. X
  635. X*catch tag exp, Sets up a dynamic catch frame using tag. Then evaluates exp.
  636. X
  637. X*throw tag value, finds the nearest *catch with an EQ tag, and cause it to
  638. Xreturn value.
  639. X
  640. X[Procedures in main program siod.c]
  641. X
  642. Xcfib is the same as standard-fib. You can time it and compare it with
  643. Xstandard-fib to get an idea of the overhead of interpretation.
  644. X
  645. Xvms-debug invokes the VMS debugger. The one optional argument is
  646. Xa string of vms-debugger commands. To show the current call
  647. Xstack and then continue execution:
  648. X
  649. X    (vms-debug "set module/all;show calls;go")`032
  650. X
  651. XOr, to single step and run at the same time:
  652. X
  653. X    (vms-debug "for i=1 to 100 do (STEP);go")
  654. X
  655. XOr, to set up a breakpoint on errors:
  656. X
  657. X    (vms-debug "set module slib;set break err;go")
  658. X
  659. X
  660. X[Utility procedures in siod.scm:]
  661. X
  662. XShows how to define macros.
  663. X
  664. Xcadr,caddr,cdddr,replace,list.
  665. X
  666. X(defvar variable default-value)
  667. X
  668. XAnd for us old maclisp hackers, setq and defun, and progn, etc.
  669. X
  670. Xcall-with-current-continuation
  671. X
  672. XImplemented in terms of *catch and *throw. So upward continuations
  673. Xare not allowed.
  674. X
  675. XA simple backquote (quasi-quote) implementation.
  676. X
  677. Xcond, a macro.
  678. X
  679. Xappend
  680. X
  681. Xnconc
  682. X
  683. X[A streams implementation:]
  684. X
  685. XThe first thing we must do is decide how to represent a stream.
  686. XThere is only one reasonable data structure available to us, the list.
  687. XSo we might use (<stream-car> <cache-flag> <cdr-cache> <cdr-procedure>)
  688. X
  689. Xthe-empty-stream is just ().
  690. X
  691. Xempty-stream?
  692. X
  693. Xhead
  694. X
  695. Xtail
  696. X
  697. Xcons-stream is a special form. Wraps a lambda around the second argument.
  698. X
  699. X*cons-stream is the low-level constructor used by cons-stream.
  700. X
  701. Xfasload, fasldump. Take the obvious arguments, and are implemented
  702. Xin terms of fast-read and fast-print.
  703. X
  704. Xcompile-file.`032
  705. X
  706. X[Arrays:]
  707. X
  708. X(cons-array size [type]) Where [type] is double, long, string, lisp or nil.
  709. X(aref array index)
  710. X(aset array index value)`032
  711. X
  712. Xfasload and fasdump are effective ways of storing and restoring numeric
  713. Xarray data.
  714. X
  715. X[Benchmarks:]
  716. X
  717. XA standard-fib procedure is included in siod.scm so that everyone will
  718. Xuse the same definition in any reports of speed. Make sure the return
  719. Xresult is correct. use command line argument of
  720. X %siod -h100000 -isiod.scm
  721. X
  722. X(standard-fib 10) => 55 ; 795 cons work.
  723. X(standard-fib 15) => 610 ; 8877 cons work.
  724. X(standard-fib 20) => 6765 ; 98508 cons work.
  725. X
  726. X[Porting:]
  727. X
  728. XSee the #ifdef definition of myruntime, which
  729. Xshould be defined to return a double float, the number of cpu seconds
  730. Xused by the process so far. It uses the the tms_utime slot, and assumes
  731. Xa clock cycle of 1/60'th of a second.
  732. X
  733. XIf your system or C runtime needs to poll for the interrupt signal
  734. Xmechanism to work, then define INTERRUPT_CHECK to be something
  735. Xuseful.
  736. X
  737. XThe STACK_LIMIT and STACK_CHECK macros may need to be conditionized.
  738. XThey currently assume stack growth downward in virtual address.
  739. XThe subr (%%stack-limit setting non-verbose) may be used to change the
  740. Xlimits at runtime.
  741. X
  742. XThe stack and register marking code used in the mark-and-sweep GC
  743. Xis unlikely to work on machines that do not keep the procedure call
  744. Xstack in main memory at all times. It is assumed that setjmp saves
  745. Xall registers into the jmp_buff data structure.
  746. X
  747. XIf the stack is not always aligned (in LISP-PTR sense) then the`032
  748. Xgc_mark_and_sweep procedure will not work properly.`032
  749. X
  750. XExample, assuming a byte addressed 32-bit pointer machine:
  751. X
  752. Xstack_start_ptr: [LISP-PTR(4)]`032
  753. X                 [LISP-PTR(4)]
  754. X                 [RANDOM(4)]
  755. X                 [RANDOM(2)]
  756. X                 [LISP-PTR(4)]
  757. X                 [LISP-PTR(4)]
  758. X                 [RANDOM(2)]
  759. X                 [LISP-PTR(4)]
  760. X                 [LISP-PTR(4)]
  761. Xstack_end:       [LISP-PTR(4)]
  762. X
  763. XAs mark_locations goes from start to end it will get off proper alignment
  764. Xsomewhere in the middle, and therefore the stack marking operation will
  765. Xnot properly identify some valid lisp pointers.
  766. X
  767. XFortunately there is an easy fix to this. A more aggressive use of
  768. Xour mark_locations procedure will suffice.
  769. X
  770. XFor example, say that there might be 2-byte random objects inserted into
  771. Xthe stack. Then use two calls to mark_locations:
  772. X
  773. X mark_locations(((char *)stack_start_ptr) + 0,((char *)&stack_end) + 0);
  774. X mark_locations(((char *)stack_start_ptr) + 2,((char *)&stack_end) + 2);
  775. X
  776. XIf we think there might be 1-byte random objects, then 4 calls are required:
  777. X
  778. X mark_locations(((char *)stack_start_ptr) + 0,((char *)&stack_end) + 0);
  779. X mark_locations(((char *)stack_start_ptr) + 1,((char *)&stack_end) + 1);
  780. X mark_locations(((char *)stack_start_ptr) + 2,((char *)&stack_end) + 2);
  781. X mark_locations(((char *)stack_start_ptr) + 3,((char *)&stack_end) + 3);
  782. X
  783. X
  784. X[Interface to other programs:]
  785. X
  786. XIf your main program does not want to actually have a read/eval/print
  787. Xloop, and instead wants to do something else entirely, then use
  788. Xthe routine set_repl_hooks to set up for procedures for:
  789. X
  790. X * putting the prompt "> " and other info strings to standard output.
  791. X
  792. X * reading (getting) an expression
  793. X
  794. X * evaluating an expression
  795. X
  796. X * printing an expression.
  797. X
  798. XThe routine get_eof_val may be called inside your reading procedure
  799. Xto return a value that will cause exit from the read/eval/print loop.
  800. X
  801. XIn order to call a single C function in the context of the repl loop,
  802. Xyou can do the following:
  803. X
  804. Xint flag = 0;
  805. X
  806. Xvoid my_puts(st)
  807. X char *st;
  808. X`123`125
  809. X
  810. XLISP my_reader()
  811. X`123if (flag == 1)
  812. X  return(get_eof_val());
  813. X flag == 1;
  814. X return(NIL);`125
  815. X
  816. XLISP my_eval(x)
  817. X LISP x;
  818. X`123call_my_c_function();
  819. X return(NIL);`125
  820. X
  821. XLISP my_print(x)
  822. X LISP x;
  823. X`123`125
  824. X
  825. Xdo_my_c_function()
  826. X`123set_repl_hooks(my_puts,my_read,my_eval,my_print);
  827. X repl_driver(1, /* or 0 if we do not want lisp's SIGINT handler */
  828. X             0);`125
  829. X
  830. X
  831. XIf you need a completely different read-eval-print-loop, for example
  832. Xone based in X-Window procedures such as XtAddInput, then you may want to
  833. Xhave your own input-scanner and utilize a read-from-string kind of
  834. Xfunction.
  835. X
  836. X
  837. X[User Type Extension:]
  838. X
  839. XThere are 5 user types currently available. tc_user_1 through tc_user_5.
  840. XIf you use them then you must at least tell the garbage collector about
  841. Xthem. To do this you must have 4 functions,
  842. X * a user_relocate, takes a object and returns a new copy.
  843. X * a user_scan, takes an object and calls relocate on its subparts.
  844. X * a user_mark, takes an object and calls gc_mark on its subparts or
  845. X                it may return one of these to avoid stack growth.
  846. X * a user_free, takes an object to hack before it gets onto the freelist.
  847. X
  848. Xset_gc_hooks(type,
  849. X             user_relocate_fcn,
  850. X             user_scan_fcn,
  851. X             user_mark_fcn,
  852. X             user_free_fcn,
  853. X             &kind_of_gc);
  854. X
  855. Xkind_of_gc should be a long. It will receive 0 for mark-and-sweep, 1 for
  856. Xstop-and-copy. Therefore set_gc_hooks should be called AFTER process_cla.
  857. XYou must specify a relocate function with stop-and-copy. The scan
  858. Xfunction may be NULL if your user types will not have lisp objects in them.
  859. XUnder mark-and-sweep the mark function is required but the free function
  860. Xmay be NULL.
  861. X
  862. XSee SIOD.C for a very simple string-append implementation example.
  863. X
  864. XYou might also want to extend the printer. This is optional.
  865. X
  866. Xset_print_hooks(type,fcn);
  867. X
  868. XThe fcn receives the object which should be printed to its second
  869. Xargument, a FILE*.
  870. X
  871. XThe evaluator may also be extended, with the "application" of user defined
  872. Xtypes following in the manner of an MSUBR.
  873. X
  874. XLastly there is a simple read macro facility.
  875. X
  876. Xvoid set_read_hooks(char *all_set,char *end_set,
  877. X`009`009    LISP (*fcn1)(),LISP (*fcn2)())
  878. X
  879. XAll_set is a string of all read macros. end_set are those
  880. Xthat will end the current token.
  881. X
  882. XThe fcn1 will receive the character used to trigger
  883. Vit and the struct gen_readio * being read from. It should return a lisp objec
  884. Xt.
  885. X
  886. Xthe fnc2 is optional, and is a user hook into the token => lisp object
  887. Xconversion.
  888. $ GOSUB UNPACK_FILE
  889.  
  890. $ FILE_IS = "SIOD.H"
  891. $ CHECKSUM_IS = 678258050
  892. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  893. X/* Scheme In One Defun, but in C this time.
  894. X`032
  895. X *                   COPYRIGHT (c) 1988-1992 BY                             *
  896. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  897. X *        See the source file SLIB.C for more information.                  *
  898. X
  899. X*/
  900. X
  901. Xstruct obj
  902. X`123short gc_mark;
  903. X short type;
  904. X union `123struct `123struct obj * car;
  905. X`009`009struct obj * cdr;`125 cons;
  906. X`009struct `123double data;`125 flonum;
  907. X`009struct `123char *pname;
  908. X`009`009struct obj * vcell;`125 symbol;
  909. X`009struct `123char *name;
  910. X`009`009struct obj * (*f)(
  911. X#if  !defined(VMS) && !defined(CRAY)
  912. X`009`009`009`009  ...
  913. X#endif
  914. X`009`009`009`009  );`125 subr;
  915. X`009struct `123struct obj *env;
  916. X`009`009struct obj *code;`125 closure;
  917. X`009struct `123long dim;
  918. X`009`009long *data;`125 long_array;
  919. X`009struct `123long dim;
  920. X`009`009double *data;`125 double_array;
  921. X`009struct `123long dim;
  922. X`009`009char *data;`125 string;
  923. X`009struct `123long dim;
  924. X`009`009struct obj **data;`125 lisp_array;
  925. X`009struct `123FILE *f;
  926. X`009`009char *name;`125 c_file;`125
  927. X storage_as;`125;
  928. X
  929. X#define CAR(x) ((*x).storage_as.cons.car)
  930. X#define CDR(x) ((*x).storage_as.cons.cdr)
  931. X#define PNAME(x) ((*x).storage_as.symbol.pname)
  932. X#define VCELL(x) ((*x).storage_as.symbol.vcell)
  933. X#define SUBRF(x) (*((*x).storage_as.subr.f))
  934. X#define FLONM(x) ((*x).storage_as.flonum.data)
  935. X
  936. X#define NIL ((struct obj *) 0)
  937. X#define EQ(x,y) ((x) == (y))
  938. X#define NEQ(x,y) ((x) != (y))
  939. X#define NULLP(x) EQ(x,NIL)
  940. X#define NNULLP(x) NEQ(x,NIL)
  941. X
  942. X#define TYPE(x) (((x) == NIL) ? 0 : ((*(x)).type))
  943. X
  944. X#define TYPEP(x,y) (TYPE(x) == (y))
  945. X#define NTYPEP(x,y) (TYPE(x) != (y))
  946. X
  947. X#define tc_nil    0
  948. X#define tc_cons   1
  949. X#define tc_flonum 2
  950. X#define tc_symbol 3
  951. X#define tc_subr_0 4
  952. X#define tc_subr_1 5
  953. X#define tc_subr_2 6
  954. X#define tc_subr_3 7
  955. X#define tc_lsubr  8
  956. X#define tc_fsubr  9
  957. X#define tc_msubr  10
  958. X#define tc_closure 11
  959. X#define tc_free_cell 12
  960. X#define tc_string       13
  961. X#define tc_double_array 14
  962. X#define tc_long_array   15
  963. X#define tc_lisp_array   16
  964. X#define tc_c_file       17
  965. X#define tc_user_1 50
  966. X#define tc_user_2 51
  967. X#define tc_user_3 52
  968. X#define tc_user_4 53
  969. X#define tc_user_5 54
  970. X
  971. X#define FO_fetch 127
  972. X#define FO_store 126
  973. X#define FO_list  125
  974. X#define FO_listd 124
  975. X
  976. X#define tc_table_dim 100
  977. X
  978. Xtypedef struct obj* LISP;
  979. X
  980. X#define CONSP(x)   TYPEP(x,tc_cons)
  981. X#define FLONUMP(x) TYPEP(x,tc_flonum)
  982. X#define SYMBOLP(x) TYPEP(x,tc_symbol)
  983. X
  984. X#define NCONSP(x)   NTYPEP(x,tc_cons)
  985. X#define NFLONUMP(x) NTYPEP(x,tc_flonum)
  986. X#define NSYMBOLP(x) NTYPEP(x,tc_symbol)
  987. X
  988. X#define TKBUFFERN 256
  989. X
  990. Xstruct gen_readio
  991. X`123int (*getc_fcn)(char *);
  992. X void (*ungetc_fcn)(int, char *);
  993. X char *cb_argument;`125;
  994. X
  995. X#define GETC_FCN(x) (*((*x).getc_fcn))((*x).cb_argument)
  996. X#define UNGETC_FCN(c,x) (*((*x).ungetc_fcn))(c,(*x).cb_argument)
  997. X
  998. Xvoid process_cla(int argc,char **argv,int warnflag);
  999. Xvoid print_welcome(void);
  1000. Xvoid print_hs_1(void);
  1001. Xvoid print_hs_2(void);
  1002. Xlong no_interrupt(long n);
  1003. XLISP get_eof_val(void);
  1004. Xvoid repl_driver(long want_sigint,long want_init);
  1005. Xvoid set_repl_hooks(void (*puts_f)(),
  1006. X`009`009    LISP (*read_f)(),
  1007. X`009`009    LISP (*eval_f)(),
  1008. X`009`009    void (*print_f)());
  1009. Xvoid repl(void) ;
  1010. Xvoid err(char *message, LISP x);
  1011. Xchar *get_c_string(LISP x);
  1012. Xlong get_c_long(LISP x);
  1013. XLISP lerr(LISP message, LISP x);
  1014. X
  1015. XLISP newcell(long type);
  1016. XLISP cons(LISP x,LISP y);
  1017. XLISP consp(LISP x);
  1018. XLISP car(LISP x);
  1019. XLISP cdr(LISP x);
  1020. XLISP setcar(LISP cell, LISP value);
  1021. XLISP setcdr(LISP cell, LISP value);
  1022. XLISP flocons(double x);
  1023. XLISP numberp(LISP x);
  1024. XLISP plus(LISP x,LISP y);
  1025. XLISP ltimes(LISP x,LISP y);
  1026. XLISP difference(LISP x,LISP y);
  1027. XLISP quotient(LISP x,LISP y);
  1028. XLISP greaterp(LISP x,LISP y);
  1029. XLISP lessp(LISP x,LISP y);
  1030. XLISP eq(LISP x,LISP y);
  1031. XLISP eql(LISP x,LISP y);
  1032. XLISP symcons(char *pname,LISP vcell);
  1033. XLISP symbolp(LISP x);
  1034. XLISP symbol_boundp(LISP x,LISP env);
  1035. XLISP symbol_value(LISP x,LISP env);
  1036. XLISP cintern(char *name);
  1037. XLISP rintern(char *name);
  1038. XLISP subrcons(long type, char *name, LISP (*f)());
  1039. XLISP closure(LISP env,LISP code);
  1040. Xvoid gc_protect(LISP *location);
  1041. Xvoid gc_protect_n(LISP *location,long n);
  1042. Xvoid gc_protect_sym(LISP *location,char *st);
  1043. X
  1044. Xvoid init_storage(void);
  1045. X
  1046. Xvoid init_subr(char *name, long type, LISP (*fcn)());
  1047. XLISP assq(LISP x,LISP alist);
  1048. XLISP delq(LISP elem,LISP l);
  1049. Xvoid set_gc_hooks(long type,
  1050. X`009`009  LISP (*rel)(),
  1051. X`009`009  LISP (*mark)(),
  1052. X`009`009  void (*scan)(),
  1053. X`009`009  void (*free)(),
  1054. X`009`009  long *kind);
  1055. XLISP gc_relocate(LISP x);
  1056. XLISP user_gc(LISP args);
  1057. XLISP gc_status(LISP args);
  1058. Xvoid set_eval_hooks(long type,LISP (*fcn)());
  1059. XLISP leval(LISP x,LISP env);
  1060. XLISP symbolconc(LISP args);
  1061. Xvoid set_print_hooks(long type,void (*fcn)());
  1062. XLISP lprin1f(LISP exp,FILE *f);
  1063. XLISP lprint(LISP exp);
  1064. XLISP lread(void);
  1065. XLISP lreadtk(long j);
  1066. XLISP lreadf(FILE *f);
  1067. Xvoid set_read_hooks(char *all_set,char *end_set,
  1068. X`009`009    LISP (*fcn1)(),LISP (*fcn2)());
  1069. XLISP oblistfn(void);
  1070. XLISP vload(char *fname,long cflag);
  1071. XLISP load(LISP fname,LISP cflag);
  1072. XLISP save_forms(LISP fname,LISP forms,LISP how);
  1073. XLISP quit(void);
  1074. XLISP nullp(LISP x);
  1075. Xvoid init_subrs();
  1076. XLISP strcons(long length,char *data);
  1077. XLISP read_from_string(LISP x);
  1078. XLISP aref1(LISP a,LISP i);
  1079. XLISP aset1(LISP a,LISP i,LISP v);
  1080. XLISP cons_array(LISP dim,LISP kind);
  1081. XLISP string_append(LISP args);
  1082. X
  1083. Xvoid init_subrs(void);
  1084. X
  1085. XLISP copy_list(LISP);
  1086. X
  1087. X
  1088. Xlong c_sxhash(LISP,long);
  1089. XLISP sxhash(LISP,LISP);
  1090. X
  1091. XLISP href(LISP,LISP);
  1092. XLISP hset(LISP,LISP,LISP);
  1093. X
  1094. XLISP fast_print(LISP,LISP);
  1095. XLISP fast_read(LISP);
  1096. X
  1097. XLISP equal(LISP,LISP);
  1098. X
  1099. XLISP assoc(LISP x,LISP alist);
  1100. X
  1101. XLISP make_list(LISP x,LISP v);
  1102. X
  1103. Xvoid set_fatal_exit_hook(void (*fcn)(void));
  1104. X
  1105. XLISP parse_number(LISP x);
  1106. $ GOSUB UNPACK_FILE
  1107.  
  1108. $ FILE_IS = "SIOD.SCM"
  1109. $ CHECKSUM_IS = 1594915310
  1110. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  1111. V;; SIOD: Scheme In One Defun                                    -*-mode:lisp-
  1112. X*-
  1113. X;;
  1114. V;; *                        COPYRIGHT (c) 1989-1992 BY                   `032
  1115. X   *
  1116. V;; *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.  `032
  1117. X   *
  1118. V;; *        See the source file SLIB.C for more information.             `032
  1119. X   *
  1120. X
  1121. X(puts  ";; Optional Runtime Library for Release 2.7
  1122. X")
  1123. X
  1124. X(define list (lambda n n))
  1125. X
  1126. X(define (sublis l exp)
  1127. X  (if (cons? exp)
  1128. X      (cons (sublis l (car exp))
  1129. X`009    (sublis l (cdr exp)))
  1130. X      (let ((cell (assq exp l)))
  1131. X`009(if cell (cdr cell) exp))))
  1132. X
  1133. X(define (caar x) (car (car x)))
  1134. X(define (cadr x) (car (cdr x)))
  1135. X(define (cdar x) (cdr (car x)))
  1136. X(define (cddr x) (cdr (cdr x)))
  1137. X
  1138. X(define (caddr x) (car (cdr (cdr x))))
  1139. X(define (cdddr x) (cdr (cdr (cdr x))))
  1140. X
  1141. X(define consp pair?)
  1142. X
  1143. X(define (replace before after)
  1144. X  (set-car! before (car after))
  1145. X  (set-cdr! before (cdr after))
  1146. X  after)
  1147. X
  1148. X(define (prognify forms)
  1149. X  (if (null? (cdr forms))
  1150. X      (car forms)
  1151. X    (cons 'begin forms)))
  1152. X
  1153. X(define (defmac-macro form)
  1154. X  (let ((sname (car (cadr form)))
  1155. X`009(argl (cdr (cadr form)))
  1156. X`009(fname nil)
  1157. X`009(body (prognify (cddr form))))
  1158. X    (set! fname (symbolconc sname '-macro))
  1159. X    (list 'begin
  1160. X`009  (list 'define (cons fname argl)
  1161. X`009`009(list 'replace (car argl) body))
  1162. X`009  (list 'define sname (list 'quote fname)))))
  1163. X
  1164. X(define defmac 'defmac-macro)
  1165. X
  1166. X(defmac (push form)
  1167. X  (list 'set! (caddr form)
  1168. X`009(list 'cons (cadr form) (caddr form))))
  1169. X
  1170. X(defmac (pop form)
  1171. X  (list 'let (list (list 'tmp (cadr form)))
  1172. X`009(list 'set! (cadr form) '(cdr tmp))
  1173. X`009'(car tmp)))
  1174. X
  1175. X(defmac (defvar form)
  1176. X  (list 'or
  1177. X`009(list 'symbol-bound? (list 'quote (cadr form)))
  1178. X`009(list 'define (cadr form) (caddr form))))
  1179. X
  1180. X(defmac (defun form)
  1181. X  (cons 'define
  1182. X`009(cons (cons (cadr form) (caddr form))
  1183. X`009      (cdddr form))))
  1184. X
  1185. X(defmac (setq form)
  1186. X  (let ((l (cdr form))
  1187. X`009(result nil))
  1188. X    (define (loop)
  1189. X      (if l
  1190. X`009  (begin (push (list 'set! (car l) (cadr l)) result)
  1191. X`009`009 (set! l (cddr l))
  1192. X`009`009 (loop))))
  1193. X    (loop)
  1194. X    (prognify (reverse result))))
  1195. X `032
  1196. X `032
  1197. X(define progn begin)
  1198. X
  1199. X(define the-empty-stream ())
  1200. X
  1201. X(define empty-stream? null?)
  1202. X
  1203. X(define (*cons-stream head tail-future)
  1204. X  (list head () () tail-future))
  1205. X
  1206. X(define head car)
  1207. X
  1208. X(define (tail x)
  1209. X  (if (car (cdr x))
  1210. X      (car (cdr (cdr x)))
  1211. X      (let ((value ((car (cdr (cdr (cdr x)))))))
  1212. X`009(set-car! (cdr x) t)
  1213. X`009(set-car! (cdr (cdr x)) value))))
  1214. X
  1215. X(defmac (cons-stream form)
  1216. X  (list '*cons-stream
  1217. X`009(cadr form)
  1218. X`009(list 'lambda () (caddr form))))
  1219. X
  1220. X(define (enumerate-interval low high)
  1221. X  (if (> low high)
  1222. X      the-empty-stream
  1223. X      (cons-stream low (enumerate-interval (+ low 1) high))))
  1224. X
  1225. X(define (print-stream-elements x)
  1226. X  (if (empty-stream? x)
  1227. X      ()
  1228. X      (begin (print (head x))
  1229. X`009     (print-stream-elements (tail x)))))
  1230. X
  1231. X(define (sum-stream-elements x)
  1232. X  (define (loop acc x)
  1233. X    (if (empty-stream? x)
  1234. X`009acc
  1235. X      (loop (+ (head x) acc) (tail x))))
  1236. X  (loop 0 x))
  1237. X
  1238. X(define (standard-fib x)
  1239. X  (if (< x 2)
  1240. X      x
  1241. X      (+ (standard-fib (- x 1))
  1242. X`009 (standard-fib (- x 2)))))
  1243. X
  1244. X(define (call-with-current-continuation fcn)
  1245. X  (let ((tag (cons nil nil)))
  1246. X    (*catch tag
  1247. X`009    (fcn (lambda (value)
  1248. X`009`009   (*throw tag value))))))
  1249. X
  1250. X
  1251. X(defun atom (x)
  1252. X  (not (consp x)))
  1253. X
  1254. X(define eq eq?)
  1255. X
  1256. X(defmac (cond form)
  1257. X  (cond-convert (cdr form)))
  1258. X
  1259. X(define null null?)
  1260. X
  1261. X(defun cond-convert (l)
  1262. X  (if (null l)
  1263. X      ()
  1264. X    (if (null (cdar l))
  1265. X`009(if (null (cdr l))
  1266. X`009    (caar l)
  1267. X`009  (let ((rest (cond-convert (cdr l))))
  1268. X`009    (if (and (consp rest) (eq (car rest) 'or))
  1269. X`009`009(cons 'or (cons (caar l) (cdr rest)))
  1270. X`009      (list 'or (caar l) rest))))
  1271. X      (if (or (eq (caar l) 't)
  1272. X`009      (and (consp (caar l)) (eq (car (caar l)) 'quote)))
  1273. X`009  (prognify (cdar l))
  1274. X`009(list 'if
  1275. X`009      (caar l)
  1276. X`009      (prognify (cdar l))
  1277. X`009      (cond-convert (cdr l)))))))
  1278. X
  1279. X(defmac (+internal-comma form)
  1280. X  (error 'comma-not-inside-backquote))
  1281. X
  1282. X(define +internal-comma-atsign +internal-comma)
  1283. X(define +internal-comma-dot +internal-comma)
  1284. X
  1285. X(defmac (+internal-backquote form)
  1286. X  (backquotify (cdr form)))
  1287. X
  1288. X(defun backquotify (x)
  1289. X  (let (a d aa ad dqp)
  1290. X    (cond ((atom x) (list 'quote x))
  1291. X`009  ((eq (car x) '+internal-comma) (cdr x))
  1292. X`009  ((or (atom (car x))
  1293. X`009       (not (or (eq (caar x) '+internal-comma-atsign)
  1294. X`009`009`009(eq (caar x) '+internal-comma-dot))))
  1295. X`009   (setq a (backquotify (car x)) d (backquotify (cdr x))
  1296. X`009`009 ad (atom d) aa (atom a)
  1297. X`009`009 dqp (and (not ad) (eq (car d) 'quote)))
  1298. X`009   (cond ((and dqp (not (atom a)) (eq (car a) 'quote))
  1299. X`009`009  (list 'quote (cons (cadr a) (cadr d))))
  1300. X`009`009 ((and dqp (null (cadr d)))
  1301. X`009`009  (list 'list a))
  1302. X`009`009 ((and (not ad) (eq (car d) 'list))
  1303. X`009`009  (cons 'list (cons a (cdr d))))
  1304. X`009`009 (t (list 'cons a d))))
  1305. X`009  ((eq (caar x) '+internal-comma-atsign)
  1306. X`009   (list 'append (cdar x) (backquotify (cdr x))))
  1307. X`009  ((eq (caar x) '+internal-comma-dot)
  1308. X`009   (list 'nconc (cdar x)(backquotify (cdr x)))))))
  1309. X
  1310. X
  1311. X(defun append n
  1312. X  (appendl n))
  1313. X
  1314. X(defun appendl (l)
  1315. X  (cond ((null l) nil)
  1316. X`009((null (cdr l)) (car l))
  1317. X`009((null (cddr l))
  1318. X`009 (append2 (car l) (cadr l)))
  1319. X`009('else
  1320. X`009 (append2 (car l) (appendl (cdr l))))))
  1321. X
  1322. X(defun append2 (a b)
  1323. X  (if (null a)
  1324. X      b
  1325. X    (cons (car a) (append2 (cdr a) b))))
  1326. X
  1327. X(defun rplacd (a b)
  1328. X  (set-cdr! a b)
  1329. X  a)
  1330. X
  1331. X(defun nconc (a b)
  1332. X  (if (null a)
  1333. X      b
  1334. X    (rplacd (last a) b)))
  1335. X
  1336. X
  1337. X(defun last (a)
  1338. X  (cond ((null a) (error'null-arg-to-last))
  1339. X`009((null (cdr a)) a)
  1340. X`009((last (cdr a)))))
  1341. X
  1342. X(define sfib
  1343. X  (eval `096(lambda (x)
  1344. X`009   (,if (,< x 2)
  1345. X`009       x
  1346. X`009     (,+ (sfib (,- x 1))
  1347. X`009`009 (sfib (,- x 2)))))))
  1348. X
  1349. X(defvar *fasdump-hash* t)
  1350. X
  1351. X(defun fasl-open (filename mode)
  1352. X  (list (fopen filename mode)
  1353. X`009(if (or (equal? mode "rb") *fasdump-hash*)
  1354. X`009    (cons-array 100))
  1355. X`009;; If this is set NIL, then already hashed symbols will be
  1356. X`009;; optimized, and additional ones will not.
  1357. X`0090))
  1358. X
  1359. X(defun fasl-close (table)
  1360. X  (fclose (car table)))
  1361. X
  1362. X(defun fasload args
  1363. X  (let ((filename (car args))
  1364. X`009(head (and (cadr args) (cons nil nil))))
  1365. X    (let ((table (fasl-open filename "rb"))
  1366. X`009  (exp)
  1367. X`009  (tail head))
  1368. X      (while (not (eq table (setq exp (fast-read table))))
  1369. X`009(cond (head
  1370. X`009       (setq exp (cons exp nil))
  1371. X`009       (set-cdr! tail exp)
  1372. X`009       (setq tail exp))
  1373. X`009      ('else
  1374. X`009       (eval exp))))
  1375. X      (fasl-close table)
  1376. X      (and head (cdr head)))))
  1377. X
  1378. X(defun fasdump (filename forms)
  1379. X  (let ((table (fasl-open filename "wb"))
  1380. X`009(l forms))
  1381. X    (while l
  1382. X      (fast-print (car l) table)
  1383. X      (setq l (cdr l)))
  1384. X    (fasl-close table)))
  1385. X
  1386. X(defun compile-file (filename)
  1387. X  (let ((forms (load (string-append filename ".scm") t)))
  1388. X    (puts "Saving forms
  1389. X")
  1390. X    (fasdump (string-append filename ".bin")
  1391. X`009     forms)))
  1392. X
  1393. X(defvar *properties* (cons-array 100))
  1394. X
  1395. X(defun get (sym key)
  1396. X  (cdr (assq key (href *properties* sym))))
  1397. X
  1398. X(defun putprop (sym val key)
  1399. X  (let ((alist (href *properties* sym)))
  1400. X    (let ((cell (assq key alist)))
  1401. X      (cond (cell
  1402. X`009     (set-cdr! cell val))
  1403. X`009    ('else
  1404. X`009     (hset *properties* sym (cons (cons key val) alist))
  1405. X`009     val)))))
  1406. X
  1407. X(define (mapcar1 f l1)
  1408. X  (and l1 (cons (f (car l1)) (mapcar1 f (cdr l1)))))
  1409. X
  1410. X
  1411. X(define (mapcar2 f l1 l2)
  1412. X  (and l1 l2 (cons (f (car l1) (car l2)) (mapcar2 f (cdr l1) (cdr l2)))))
  1413. X
  1414. X(define (mapcar . args)
  1415. X  (cond ((null args)
  1416. X`009 (error "too few arguments"))
  1417. X`009((null (cdr args))
  1418. X`009 (error "too few arguments"))
  1419. X`009((null (cdr (cdr args)))
  1420. X`009 (mapcar1 (car args) (car (cdr args))))
  1421. X`009((null (cdr (cdr (cdr args))))
  1422. X`009 (mapcar2 (car args) (car (cdr args)) (car (cdr (cdr args)))))
  1423. X`009('else
  1424. X`009 (error "two many arguments"))))
  1425. X`009
  1426. X`009`032
  1427. X `032
  1428. X
  1429. $ GOSUB UNPACK_FILE
  1430.  
  1431. $ FILE_IS = "SLIB.C"
  1432. $ CHECKSUM_IS = 1947177271
  1433. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  1434. X/* Scheme In One Defun, but in C this time.
  1435. X`032
  1436. X *                      COPYRIGHT (c) 1988-1992 BY                          *
  1437. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  1438. X *`009`009`009   ALL RIGHTS RESERVED                              *
  1439. X
  1440. XPermission to use, copy, modify, distribute and sell this software
  1441. Xand its documentation for any purpose and without fee is hereby
  1442. Xgranted, provided that the above copyright notice appear in all copies
  1443. Xand that both that copyright notice and this permission notice appear
  1444. Xin supporting documentation, and that the name of Paradigm Associates
  1445. XInc not be used in advertising or publicity pertaining to distribution
  1446. Xof the software without specific, written prior permission.
  1447. X
  1448. XPARADIGM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  1449. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  1450. XPARADIGM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  1451. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  1452. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  1453. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  1454. XSOFTWARE.
  1455. X
  1456. X*/
  1457. X
  1458. X/*
  1459. X
  1460. Xgjc@paradigm.com
  1461. X
  1462. XParadigm Associates Inc          Phone: 617-492-6079
  1463. X29 Putnam Ave, Suite 6
  1464. XCambridge, MA 02138
  1465. X
  1466. X
  1467. X   Release 1.0: 24-APR-88
  1468. X   Release 1.1: 25-APR-88, added: macros, predicates, load. With additions by
  1469. X    Barak.Pearlmutter@DOGHEN.BOLTZ.CS.CMU.EDU: Full flonum recognizer,
  1470. X    cleaned up uses of NULL/0. Now distributed with siod.scm.
  1471. X   Release 1.2: 28-APR-88, name changes as requested by JAR@AI.AI.MIT.EDU,
  1472. X    plus some bug fixes.
  1473. X   Release 1.3: 1-MAY-88, changed env to use frames instead of alist.
  1474. X    define now works properly. vms specific function edit.
  1475. X   Release 1.4 20-NOV-89. Minor Cleanup and remodularization.
  1476. X    Now in 3 files, siod.h, slib.c, siod.c. Makes it easier to write your
  1477. X    own main loops. Some short-int changes for lightspeed C included.
  1478. X   Release 1.5 29-NOV-89. Added startup flag -g, select stop and copy
  1479. V    or mark-and-sweep garbage collection, which assumes that the stack/regist
  1480. Xer
  1481. X    marking code is correct for your architecture.`032
  1482. V   Release 2.0 1-DEC-89. Added repl_hooks, Catch, Throw. This is significantl
  1483. Xy
  1484. X    different enough (from 1.3) now that I'm calling it a major release.
  1485. X   Release 2.1 4-DEC-89. Small reader features, dot, backquote, comma.
  1486. V   Release 2.2 5-DEC-89. gc,read,print,eval, hooks for user defined datatypes
  1487. X.
  1488. X   Release 2.3 6-DEC-89. save_forms, obarray intern mechanism. comment char.
  1489. X   Release 2.3a......... minor speed-ups. i/o interrupt considerations.
  1490. X   Release 2.4 27-APR-90 gen_readr, for read-from-string.
  1491. X   Release 2.5 18-SEP-90 arrays added to SIOD.C by popular demand. inums.
  1492. X   Release 2.6 11-MAR-92 function prototypes, some remodularization.
  1493. X   Release 2.7 20-MAR-92 hash tables, fasload. Stack check.
  1494. X   Release 2.8  3-APR-92 Bug fixes, \n syntax in string reading.
  1495. X
  1496. X  */
  1497. X
  1498. X#include <stdio.h>
  1499. X#include <string.h>
  1500. X#include <ctype.h>
  1501. X#include <setjmp.h>
  1502. X#include <signal.h>
  1503. X#include <math.h>
  1504. X#include <stdlib.h>
  1505. X#include <time.h>
  1506. X
  1507. X#include "siod.h"
  1508. X#include "siodp.h"
  1509. X
  1510. XLISP heap_1,heap_2;
  1511. XLISP heap,heap_end,heap_org;
  1512. Xlong heap_size = 5000;
  1513. Xlong old_heap_used;
  1514. Xlong which_heap;
  1515. Xlong gc_status_flag = 1;
  1516. Xchar *init_file = (char *) NULL;
  1517. Xchar *tkbuffer = NULL;
  1518. Xlong gc_kind_copying = 1;
  1519. Xlong gc_cells_allocated = 0;
  1520. Xdouble gc_time_taken;
  1521. XLISP *stack_start_ptr;
  1522. XLISP freelist;
  1523. Xjmp_buf errjmp;
  1524. Xlong errjmp_ok = 0;
  1525. Xlong nointerrupt = 1;
  1526. Xlong interrupt_differed = 0;
  1527. XLISP oblistvar = NIL;
  1528. XLISP truth = NIL;
  1529. XLISP eof_val = NIL;
  1530. XLISP sym_errobj = NIL;
  1531. XLISP sym_progn = NIL;
  1532. XLISP sym_lambda = NIL;
  1533. XLISP sym_quote = NIL;
  1534. XLISP sym_dot = NIL;
  1535. XLISP open_files = NIL;
  1536. XLISP unbound_marker = NIL;
  1537. XLISP *obarray;
  1538. Xlong obarray_dim = 100;
  1539. Xstruct catch_frame *catch_framep = (struct catch_frame *) NULL;
  1540. Xvoid (*repl_puts)(char *) = NULL;
  1541. XLISP (*repl_read)(void) = NULL;
  1542. XLISP (*repl_eval)(LISP) = NULL;
  1543. Xvoid (*repl_print)(LISP) = NULL;
  1544. XLISP *inums;
  1545. Xlong inums_dim = 100;
  1546. Xstruct user_type_hooks *user_type_hooks = NULL;
  1547. Xstruct gc_protected *protected_registers = NULL;
  1548. Xjmp_buf save_regs_gc_mark;
  1549. Xdouble gc_rt;
  1550. Xlong gc_cells_collected;
  1551. Xchar *user_ch_readm = "";
  1552. Xchar *user_te_readm = "";
  1553. XLISP (*user_readm)(int, struct gen_readio *) = NULL;
  1554. XLISP (*user_readt)(char *,long, int *) = NULL;
  1555. Xvoid (*fatal_exit_hook)(void) = NULL;
  1556. X#ifdef THINK_C
  1557. Xint ipoll_counter = 0;
  1558. X#endif
  1559. X
  1560. Xchar *stack_limit_ptr = NULL;
  1561. Xlong stack_size =`032
  1562. X#ifdef THINK_C
  1563. X  10000;
  1564. X#else
  1565. X  50000;
  1566. X#endif
  1567. X
  1568. Xvoid process_cla(int argc,char **argv,int warnflag)
  1569. X`123int k;
  1570. X for(k=1;k<argc;++k)
  1571. X   `123if (strlen(argv[k])<2) continue;
  1572. X    if (argv[k][0] != '-')
  1573. X      `123if (warnflag) printf("bad arg: %s\n",argv[k]);continue;`125
  1574. X    switch(argv[k][1])
  1575. X      `123case 'h':
  1576. X`009 heap_size = atol(&(argv[k][2]));
  1577. X`009 break;
  1578. X       case 'o':
  1579. X`009 obarray_dim = atol(&(argv[k][2]));
  1580. X`009 break;
  1581. X       case 'i':
  1582. X`009 init_file = &(argv[k][2]);
  1583. X`009 break;
  1584. X       case 'n':
  1585. X`009 inums_dim = atol(&(argv[k][2]));
  1586. X`009 break;
  1587. X       case 'g':
  1588. X`009 gc_kind_copying = atol(&(argv[k][2]));
  1589. X`009 break;
  1590. X       case 's':
  1591. X`009 stack_size = atol(&(argv[k][2]));
  1592. X`009 break;
  1593. X       default:
  1594. X`009 if (warnflag) printf("bad arg: %s\n",argv[k]);`125`125`125
  1595. X
  1596. Xvoid print_welcome(void)
  1597. X`123printf("Welcome to SIOD, Scheme In One Defun, Version 2.8\n");
  1598. X printf("(C) Copyright 1988-1992 Paradigm Associates Inc.\n");`125
  1599. X
  1600. Xvoid print_hs_1(void)
  1601. X`123printf("heap_size = %ld cells, %ld bytes. %ld inums. GC is %s\n",
  1602. X        heap_size,heap_size*sizeof(struct obj),
  1603. X`009inums_dim,
  1604. X`009(gc_kind_copying == 1) ? "stop and copy" : "mark and sweep");`125
  1605. X
  1606. Xvoid print_hs_2(void)
  1607. X`123if (gc_kind_copying == 1)
  1608. X   printf("heap_1 at 0x%lX, heap_2 at 0x%lX\n",heap_1,heap_2);
  1609. X else
  1610. X   printf("heap_1 at 0x%lX\n",heap_1);`125
  1611. X
  1612. Xlong no_interrupt(long n)
  1613. X`123long x;
  1614. X x = nointerrupt;
  1615. X nointerrupt = n;
  1616. X if ((nointerrupt == 0) && (interrupt_differed == 1))
  1617. X   `123interrupt_differed = 0;
  1618. X    err_ctrl_c();`125
  1619. X return(x);`125
  1620. X
  1621. Xvoid handle_sigfpe(int sig SIG_restargs)
  1622. X`123signal(SIGFPE,handle_sigfpe);
  1623. X err("floating point exception",NIL);`125
  1624. X
  1625. Xvoid handle_sigint(int sig SIG_restargs)
  1626. X`123signal(SIGINT,handle_sigint);
  1627. X if (nointerrupt == 1)
  1628. X   interrupt_differed = 1;
  1629. X else
  1630. X   err_ctrl_c();`125
  1631. X
  1632. Xvoid err_ctrl_c(void)
  1633. X`123err("control-c interrupt",NIL);`125
  1634. X
  1635. XLISP get_eof_val(void)
  1636. X`123return(eof_val);`125
  1637. X
  1638. Xvoid repl_driver(long want_sigint,long want_init)
  1639. X`123int k;
  1640. X LISP stack_start;
  1641. X stack_start_ptr = &stack_start;
  1642. X stack_limit_ptr = STACK_LIMIT(stack_start_ptr,stack_size);
  1643. X k = setjmp(errjmp);
  1644. X if (k == 2) return;
  1645. X if (want_sigint) signal(SIGINT,handle_sigint);
  1646. X signal(SIGFPE,handle_sigfpe);
  1647. X close_open_files();
  1648. X catch_framep = (struct catch_frame *) NULL;
  1649. X errjmp_ok = 1;
  1650. X interrupt_differed = 0;
  1651. X nointerrupt = 0;
  1652. X if (want_init && init_file && (k == 0)) vload(init_file,0);
  1653. X repl();`125
  1654. X
  1655. X#ifdef vms
  1656. Xdouble myruntime(void)
  1657. X`123double total;
  1658. X struct tbuffer b;
  1659. X times(&b);
  1660. X total = b.proc_user_time;
  1661. X total += b.proc_system_time;
  1662. X return(total / CLK_TCK);`125
  1663. X#else
  1664. X#ifdef unix
  1665. X#include <sys/types.h>
  1666. X#include <sys/times.h>
  1667. Xdouble myruntime(void)
  1668. X`123double total;
  1669. X struct tms b;
  1670. X times(&b);
  1671. X total = b.tms_utime;
  1672. X total += b.tms_stime;
  1673. X return(total / 60.0);`125
  1674. X#else
  1675. X#ifdef THINK_C
  1676. Xdouble myruntime(void)
  1677. X`123return(((double) clock()) / ((double) CLOCKS_PER_SEC));`125
  1678. X#else
  1679. Xdouble myruntime(void)
  1680. X`123time_t x;
  1681. X time(&x);
  1682. X return((double) x);`125
  1683. X#endif
  1684. X#endif
  1685. X#endif
  1686. X
  1687. Xvoid set_repl_hooks(void (*puts_f)(),
  1688. X`009`009    LISP (*read_f)(),
  1689. X`009`009    LISP (*eval_f)(),
  1690. X`009`009    void (*print_f)())
  1691. X`123repl_puts = puts_f;
  1692. X repl_read = read_f;
  1693. X repl_eval = eval_f;
  1694. X repl_print = print_f;`125
  1695. X
  1696. Xvoid fput_st(FILE *f,char *st)
  1697. X`123long flag;
  1698. X flag = no_interrupt(1);
  1699. X fprintf(f,"%s",st);
  1700. X no_interrupt(flag);`125
  1701. X
  1702. Xvoid put_st(char *st)
  1703. X`123fput_st(stdout,st);`125
  1704. X    `032
  1705. Xvoid grepl_puts(char *st)
  1706. X`123if (repl_puts == NULL)
  1707. X   put_st(st);
  1708. X else
  1709. X   (*repl_puts)(st);`125
  1710. X    `032
  1711. Xvoid repl(void)`032
  1712. X`123LISP x,cw;
  1713. X double rt;
  1714. X while(1)
  1715. V   `123if ((gc_kind_copying == 1) && ((gc_status_flag) `124`124 heap >= heap_
  1716. Xend))
  1717. X     `123rt = myruntime();
  1718. X      gc_stop_and_copy();
  1719. X      sprintf(tkbuffer,
  1720. X`009      "GC took %g seconds, %ld compressed to %ld, %ld free\n",
  1721. X`009      myruntime()-rt,old_heap_used,heap-heap_org,heap_end-heap);
  1722. X      grepl_puts(tkbuffer);`125
  1723. X    grepl_puts("> ");
  1724. X    if (repl_read == NULL) x = lread();
  1725. X    else x = (*repl_read)();
  1726. X    if EQ(x,eof_val) break;
  1727. X    rt = myruntime();
  1728. X    if (gc_kind_copying == 1)
  1729. X      cw = heap;
  1730. X    else
  1731. X      `123gc_cells_allocated = 0;
  1732. X       gc_time_taken = 0.0;`125
  1733. X    if (repl_eval == NULL) x = leval(x,NIL);
  1734. X    else x = (*repl_eval)(x);
  1735. X    if (gc_kind_copying == 1)
  1736. X      sprintf(tkbuffer,
  1737. X`009      "Evaluation took %g seconds %ld cons work\n",
  1738. X`009      myruntime()-rt,
  1739. X`009      heap-cw);
  1740. X    else
  1741. X      sprintf(tkbuffer,
  1742. X`009      "Evaluation took %g seconds (%g in gc) %ld cons work\n",
  1743. X`009      myruntime()-rt,
  1744. X`009      gc_time_taken,
  1745. X`009      gc_cells_allocated);
  1746. X    grepl_puts(tkbuffer);
  1747. X    if (repl_print == NULL) lprint(x);
  1748. X    else (*repl_print)(x);`125`125
  1749. X
  1750. Xvoid set_fatal_exit_hook(void (*fcn)(void))
  1751. X`123fatal_exit_hook = fcn;`125
  1752. X
  1753. Xvoid err(char *message, LISP x)
  1754. X`123nointerrupt = 1;
  1755. X if NNULLP(x)`032
  1756. X    printf("ERROR: %s (see errobj)\n",message);
  1757. X  else printf("ERROR: %s\n",message);
  1758. X if (errjmp_ok == 1) `123setvar(sym_errobj,x,NIL); longjmp(errjmp,1);`125
  1759. X printf("FATAL ERROR DURING STARTUP OR CRITICAL CODE SECTION\n");
  1760. X if (fatal_exit_hook)
  1761. X   (*fatal_exit_hook)();
  1762. X else
  1763. X   exit(1);`125
  1764. X
  1765. Xvoid err_stack(char *ptr)
  1766. X     /* The user could be given an option to continue here */
  1767. X`123err("the currently assigned stack limit has been exceded",NIL);`125
  1768. X
  1769. XLISP stack_limit(LISP amount,LISP silent)
  1770. X`123if NNULLP(amount)
  1771. X   `123stack_size = get_c_long(amount);
  1772. X    stack_limit_ptr = STACK_LIMIT(stack_start_ptr,stack_size);`125
  1773. X if NULLP(silent)
  1774. X   `123sprintf(tkbuffer,"Stack_size = %ld bytes, [%08lX,0%08lX]\n",
  1775. X`009    stack_size,stack_start_ptr,stack_limit_ptr);
  1776. X    put_st(tkbuffer);
  1777. X    return(NIL);`125
  1778. X else
  1779. X   return(flocons(stack_size));`125
  1780. X
  1781. Xchar *get_c_string(LISP x)
  1782. X`123if TYPEP(x,tc_symbol)
  1783. X   return(PNAME(x));
  1784. X else if TYPEP(x,tc_string)
  1785. X   return(x->storage_as.string.data);
  1786. X else
  1787. X   err("not a symbol or string",x);`125
  1788. X
  1789. XLISP lerr(LISP message, LISP x)
  1790. X`123err(get_c_string(message),x);
  1791. X return(NIL);`125
  1792. X
  1793. Xvoid gc_fatal_error(void)
  1794. X`123err("ran out of storage",NIL);`125
  1795. X
  1796. XLISP newcell(long type)
  1797. X`123LISP z;
  1798. X NEWCELL(z,type);
  1799. X return(z);`125
  1800. X
  1801. XLISP cons(LISP x,LISP y)
  1802. X`123LISP z;
  1803. X NEWCELL(z,tc_cons);
  1804. X CAR(z) = x;
  1805. X CDR(z) = y;
  1806. X return(z);`125
  1807. X
  1808. XLISP consp(LISP x)
  1809. X`123if CONSP(x) return(truth); else return(NIL);`125
  1810. X
  1811. XLISP car(LISP x)
  1812. X`123switch TYPE(x)
  1813. X   `123case tc_nil:
  1814. X      return(NIL);
  1815. X    case tc_cons:
  1816. X      return(CAR(x));
  1817. X    default:
  1818. X      err("wta to car",x);`125`125
  1819. X
  1820. XLISP cdr(LISP x)
  1821. X`123switch TYPE(x)
  1822. X   `123case tc_nil:
  1823. X      return(NIL);
  1824. X    case tc_cons:
  1825. X      return(CDR(x));
  1826. X    default:
  1827. X      err("wta to cdr",x);`125`125
  1828. X
  1829. XLISP setcar(LISP cell, LISP value)
  1830. X`123if NCONSP(cell) err("wta to setcar",cell);
  1831. X return(CAR(cell) = value);`125
  1832. X
  1833. XLISP setcdr(LISP cell, LISP value)
  1834. X`123if NCONSP(cell) err("wta to setcdr",cell);
  1835. X return(CDR(cell) = value);`125
  1836. X
  1837. XLISP flocons(double x)
  1838. X`123LISP z;
  1839. X long n;
  1840. X if ((inums_dim > 0) &&
  1841. X     ((x - (n = x)) == 0) &&
  1842. X     (x >= 0) &&
  1843. X     (n < inums_dim))
  1844. X   return(inums[n]);
  1845. X NEWCELL(z,tc_flonum);
  1846. X FLONM(z) = x;
  1847. X return(z);`125
  1848. X
  1849. XLISP numberp(LISP x)
  1850. X`123if FLONUMP(x) return(truth); else return(NIL);`125
  1851. X
  1852. XLISP plus(LISP x,LISP y)
  1853. X`123if NFLONUMP(x) err("wta(1st) to plus",x);
  1854. X if NFLONUMP(y) err("wta(2nd) to plus",y);
  1855. X return(flocons(FLONM(x) + FLONM(y)));`125
  1856. X
  1857. XLISP ltimes(LISP x,LISP y)
  1858. X`123if NFLONUMP(x) err("wta(1st) to times",x);
  1859. X if NFLONUMP(y) err("wta(2nd) to times",y);
  1860. X return(flocons(FLONM(x)*FLONM(y)));`125
  1861. X
  1862. XLISP difference(LISP x,LISP y)
  1863. X`123LISP z;
  1864. X if NFLONUMP(x) err("wta(1st) to difference",x);
  1865. X if NFLONUMP(y) err("wta(2nd) to difference",y);
  1866. X return(flocons(FLONM(x) - FLONM(y)));`125
  1867. X
  1868. XLISP quotient(LISP x,LISP y)
  1869. X`123LISP z;
  1870. X if NFLONUMP(x) err("wta(1st) to quotient",x);
  1871. X if NFLONUMP(y) err("wta(2nd) to quotient",y);
  1872. X return(flocons(FLONM(x)/FLONM(y)));`125
  1873. X
  1874. XLISP greaterp(LISP x,LISP y)
  1875. X`123if NFLONUMP(x) err("wta(1st) to greaterp",x);
  1876. X if NFLONUMP(y) err("wta(2nd) to greaterp",y);
  1877. X if (FLONM(x)>FLONM(y)) return(truth);
  1878. X return(NIL);`125
  1879. X
  1880. XLISP lessp(LISP x,LISP y)
  1881. X`123if NFLONUMP(x) err("wta(1st) to lessp",x);
  1882. X if NFLONUMP(y) err("wta(2nd) to lessp",y);
  1883. X if (FLONM(x)<FLONM(y)) return(truth);
  1884. X return(NIL);`125
  1885. X
  1886. XLISP eq(LISP x,LISP y)
  1887. X`123if EQ(x,y) return(truth); else return(NIL);`125
  1888. X
  1889. XLISP eql(LISP x,LISP y)
  1890. X`123if EQ(x,y) return(truth); else`032
  1891. X if NFLONUMP(x) return(NIL); else
  1892. X if NFLONUMP(y) return(NIL); else
  1893. X if (FLONM(x) == FLONM(y)) return(truth);
  1894. X return(NIL);`125
  1895. X
  1896. XLISP symcons(char *pname,LISP vcell)
  1897. X`123LISP z;
  1898. X NEWCELL(z,tc_symbol);
  1899. X PNAME(z) = pname;
  1900. X VCELL(z) = vcell;
  1901. X return(z);`125
  1902. X
  1903. XLISP symbolp(LISP x)
  1904. X`123if SYMBOLP(x) return(truth); else return(NIL);`125
  1905. X
  1906. XLISP symbol_boundp(LISP x,LISP env)
  1907. X`123LISP tmp;
  1908. X if NSYMBOLP(x) err("not a symbol",x);
  1909. X tmp = envlookup(x,env);
  1910. X if NNULLP(tmp) return(truth);
  1911. X if EQ(VCELL(x),unbound_marker) return(NIL); else return(truth);`125
  1912. X
  1913. XLISP symbol_value(LISP x,LISP env)
  1914. X`123LISP tmp;
  1915. X if NSYMBOLP(x) err("not a symbol",x);
  1916. X tmp = envlookup(x,env);
  1917. X if NNULLP(tmp) return(CAR(tmp));
  1918. X tmp = VCELL(x);
  1919. X if EQ(tmp,unbound_marker) err("unbound variable",x);
  1920. X return(tmp);`125
  1921. X
  1922. Xchar *must_malloc(unsigned long size)
  1923. X`123char *tmp;
  1924. X tmp = (char *) malloc(size);
  1925. X if (tmp == (char *)NULL) err("failed to allocate storage from system",NIL);
  1926. X return(tmp);`125
  1927. X
  1928. XLISP gen_intern(char *name,long copyp)
  1929. X`123LISP l,sym,sl;
  1930. X char *cname;
  1931. X long hash,n,c,flag;
  1932. X flag = no_interrupt(1);
  1933. X if (obarray_dim > 1)
  1934. X   `123hash = 0;
  1935. X    n = obarray_dim;
  1936. X    cname = name;
  1937. X    while(c = *cname++) hash = ((hash * 17) `094 c) % n;
  1938. X    sl = obarray[hash];`125
  1939. X else
  1940. X   sl = oblistvar;
  1941. X for(l=sl;NNULLP(l);l=CDR(l))
  1942. X   if (strcmp(name,PNAME(CAR(l))) == 0)
  1943. X     `123no_interrupt(flag);
  1944. X      return(CAR(l));`125
  1945. X if (copyp == 1)
  1946. X   `123cname = (char *) must_malloc(strlen(name)+1);
  1947. X    strcpy(cname,name);`125
  1948. X else
  1949. X   cname = name;
  1950. X sym = symcons(cname,unbound_marker);
  1951. X if (obarray_dim > 1) obarray[hash] = cons(sym,sl);
  1952. X oblistvar = cons(sym,oblistvar);
  1953. X no_interrupt(flag);
  1954. X return(sym);`125
  1955. X
  1956. XLISP cintern(char *name)
  1957. X`123return(gen_intern(name,0));`125
  1958. X
  1959. XLISP rintern(char *name)
  1960. X`123return(gen_intern(name,1));`125
  1961. X
  1962. XLISP subrcons(long type, char *name, LISP (*f)())
  1963. X`123LISP z;
  1964. X NEWCELL(z,type);
  1965. X (*z).storage_as.subr.name = name;
  1966. X (*z).storage_as.subr.f = f;
  1967. X return(z);`125
  1968. X
  1969. XLISP closure(LISP env,LISP code)
  1970. X`123LISP z;
  1971. X NEWCELL(z,tc_closure);
  1972. X (*z).storage_as.closure.env = env;
  1973. X (*z).storage_as.closure.code = code;
  1974. X return(z);`125
  1975. X
  1976. Xvoid gc_protect(LISP *location)
  1977. X`123gc_protect_n(location,1);`125
  1978. X
  1979. Xvoid gc_protect_n(LISP *location,long n)
  1980. X`123struct gc_protected *reg;
  1981. X reg = (struct gc_protected *) must_malloc(sizeof(struct gc_protected));
  1982. X (*reg).location = location;
  1983. X (*reg).length = n;
  1984. X (*reg).next = protected_registers;
  1985. X  protected_registers = reg;`125
  1986. X
  1987. Xvoid gc_protect_sym(LISP *location,char *st)
  1988. X`123*location = cintern(st);
  1989. X gc_protect(location);`125
  1990. X
  1991. Xvoid scan_registers(void)
  1992. X`123struct gc_protected *reg;
  1993. X LISP *location;
  1994. X long j,n;
  1995. X for(reg = protected_registers; reg; reg = (*reg).next)
  1996. X   `123location = (*reg).location;
  1997. X    n = (*reg).length;
  1998. X    for(j=0;j<n;++j)
  1999. X      location[j] = gc_relocate(location[j]);`125`125
  2000. X
  2001. Xvoid init_storage(void)
  2002. X`123long j;
  2003. X init_storage_1();
  2004. X init_storage_a();
  2005. X set_gc_hooks(tc_c_file,0,0,0,file_gc_free,&j);
  2006. X set_print_hooks(tc_c_file,file_prin1);`125
  2007. X
  2008. Xvoid init_storage_1(void)
  2009. X`123LISP ptr,next,end;
  2010. X long j;
  2011. X tkbuffer = (char *) must_malloc(TKBUFFERN+1);
  2012. X heap_1 = (LISP) must_malloc(sizeof(struct obj)*heap_size);
  2013. X heap = heap_1;
  2014. X which_heap = 1;
  2015. X heap_org = heap;
  2016. X heap_end = heap + heap_size;
  2017. X if (gc_kind_copying == 1)
  2018. X   heap_2 = (LISP) must_malloc(sizeof(struct obj)*heap_size);
  2019. X else
  2020. X   `123ptr = heap_org;
  2021. X    end = heap_end;
  2022. X    while(1)
  2023. X      `123(*ptr).type = tc_free_cell;
  2024. X       next = ptr + 1;
  2025. X       if (next < end)
  2026. X`009 `123CDR(ptr) = next;
  2027. X`009  ptr = next;`125
  2028. X       else
  2029. X`009 `123CDR(ptr) = NIL;
  2030. X`009  break;`125`125
  2031. X    freelist = heap_org;`125
  2032. X gc_protect(&oblistvar);
  2033. X if (obarray_dim > 1)
  2034. X   `123obarray = (LISP *) must_malloc(sizeof(LISP) * obarray_dim);
  2035. X    for(j=0;j<obarray_dim;++j)
  2036. X      obarray[j] = NIL;
  2037. X    gc_protect_n(obarray,obarray_dim);`125
  2038. X unbound_marker = cons(cintern("**unbound-marker**"),NIL);
  2039. X gc_protect(&unbound_marker);
  2040. X eof_val = cons(cintern("eof"),NIL);
  2041. X gc_protect(&eof_val);
  2042. X gc_protect_sym(&truth,"t");
  2043. X setvar(truth,truth,NIL);
  2044. X setvar(cintern("nil"),NIL,NIL);
  2045. X setvar(cintern("let"),cintern("let-internal-macro"),NIL);
  2046. X gc_protect_sym(&sym_errobj,"errobj");
  2047. X setvar(sym_errobj,NIL,NIL);
  2048. X gc_protect_sym(&sym_progn,"begin");
  2049. X gc_protect_sym(&sym_lambda,"lambda");
  2050. X gc_protect_sym(&sym_quote,"quote");
  2051. X gc_protect_sym(&sym_dot,".");
  2052. X gc_protect(&open_files);
  2053. X if (inums_dim > 0)
  2054. X   `123inums = (LISP *) must_malloc(sizeof(LISP) * inums_dim);
  2055. X    for(j=0;j<inums_dim;++j)
  2056. X      `123NEWCELL(ptr,tc_flonum);
  2057. X       FLONM(ptr) = j;
  2058. X       inums[j] = ptr;`125
  2059. X    gc_protect_n(inums,inums_dim);`125`125
  2060. X`032
  2061. Xvoid init_subr(char *name, long type, LISP (*fcn)())
  2062. X`123setvar(cintern(name),subrcons(type,name,fcn),NIL);`125
  2063. X
  2064. XLISP assq(LISP x,LISP alist)
  2065. X`123LISP l,tmp;
  2066. X for(l=alist;CONSP(l);l=CDR(l))
  2067. X   `123tmp = CAR(l);
  2068. X    if (CONSP(tmp) && EQ(CAR(tmp),x)) return(tmp);`125
  2069. X if EQ(l,NIL) return(NIL);
  2070. X err("improper list to assq",alist);`125
  2071. X
  2072. Xstruct user_type_hooks *get_user_type_hooks(long type)
  2073. X`123long j;
  2074. X if (user_type_hooks == NULL)
  2075. X   `123user_type_hooks = (struct user_type_hooks *)
  2076. X      must_malloc(sizeof(struct user_type_hooks) * tc_table_dim);
  2077. X    for(j=0;j<tc_table_dim;++j)
  2078. X      memset(&user_type_hooks[j],0,sizeof(struct user_type_hooks));`125
  2079. X if ((type >= 0) && (type < tc_table_dim))
  2080. X   return(&user_type_hooks[type]);
  2081. X else
  2082. X   err("type number out of range",NIL);`125
  2083. X
  2084. Xvoid set_gc_hooks(long type,
  2085. X`009`009  LISP (*rel)(),
  2086. X`009`009  LISP (*mark)(),
  2087. X`009`009  void (*scan)(),
  2088. X`009`009  void (*free)(),
  2089. X`009`009  long *kind)
  2090. X`123struct user_type_hooks *p;
  2091. X p = get_user_type_hooks(type);
  2092. X p->gc_relocate = rel;
  2093. X p->gc_scan = scan;
  2094. X p->gc_mark = mark;
  2095. X p->gc_free = free;
  2096. X *kind = gc_kind_copying;`125
  2097. X
  2098. XLISP gc_relocate(LISP x)
  2099. X`123LISP new;
  2100. X struct user_type_hooks *p;
  2101. X if EQ(x,NIL) return(NIL);
  2102. X if ((*x).gc_mark == 1) return(CAR(x));
  2103. X switch TYPE(x)
  2104. X   `123case tc_flonum:
  2105. X    case tc_cons:
  2106. X    case tc_symbol:
  2107. X    case tc_closure:
  2108. X    case tc_subr_0:
  2109. X    case tc_subr_1:
  2110. X    case tc_subr_2:
  2111. X    case tc_subr_3:
  2112. X    case tc_lsubr:
  2113. X    case tc_fsubr:
  2114. X    case tc_msubr:
  2115. X      if ((new = heap) >= heap_end) gc_fatal_error();
  2116. X      heap = new+1;
  2117. X      memcpy(new,x,sizeof(struct obj));
  2118. X      break;
  2119. X    default:
  2120. X      p = get_user_type_hooks(TYPE(x));
  2121. X      if (p->gc_relocate)
  2122. X`009new = (*p->gc_relocate)(x);
  2123. X      else
  2124. X`009`123if ((new = heap) >= heap_end) gc_fatal_error();
  2125. X`009 heap = new+1;
  2126. X`009 memcpy(new,x,sizeof(struct obj));`125`125
  2127. X (*x).gc_mark = 1;
  2128. X CAR(x) = new;
  2129. X return(new);`125
  2130. X
  2131. XLISP get_newspace(void)
  2132. X`123LISP newspace;
  2133. X if (which_heap == 1)
  2134. X   `123newspace = heap_2;
  2135. X    which_heap = 2;`125
  2136. X else
  2137. X   `123newspace = heap_1;
  2138. X    which_heap = 1;`125
  2139. X heap = newspace;
  2140. X heap_org = heap;
  2141. X heap_end = heap + heap_size;
  2142. X return(newspace);`125
  2143. X
  2144. Xvoid scan_newspace(LISP newspace)
  2145. X`123LISP ptr;
  2146. X struct user_type_hooks *p;
  2147. X for(ptr=newspace; ptr < heap; ++ptr)
  2148. X   `123switch TYPE(ptr)
  2149. X      `123case tc_cons:
  2150. X       case tc_closure:
  2151. X`009 CAR(ptr) = gc_relocate(CAR(ptr));
  2152. X`009 CDR(ptr) = gc_relocate(CDR(ptr));
  2153. X`009 break;
  2154. X       case tc_symbol:
  2155. X`009 VCELL(ptr) = gc_relocate(VCELL(ptr));
  2156. X`009 break;
  2157. X       case tc_flonum:
  2158. X       case tc_subr_0:
  2159. X       case tc_subr_1:
  2160. X       case tc_subr_2:
  2161. X       case tc_subr_3:
  2162. X       case tc_lsubr:
  2163. X       case tc_fsubr:
  2164. X       case tc_msubr:
  2165. X`009 break;
  2166. X       default:
  2167. X`009 p = get_user_type_hooks(TYPE(ptr));
  2168. X`009 if (p->gc_scan) (*p->gc_scan)(ptr);`125`125`125
  2169. X
  2170. Xvoid free_oldspace(LISP space,LISP end)
  2171. X`123LISP ptr;
  2172. X struct user_type_hooks *p;
  2173. X for(ptr=space; ptr < end; ++ptr)
  2174. X   if (ptr->gc_mark == 0)
  2175. X     switch TYPE(ptr)
  2176. X       `123case tc_cons:
  2177. X`009case tc_closure:
  2178. X`009case tc_symbol:
  2179. X`009case tc_flonum:
  2180. X`009case tc_subr_0:
  2181. X`009case tc_subr_1:
  2182. X`009case tc_subr_2:
  2183. X`009case tc_subr_3:
  2184. X`009case tc_lsubr:
  2185. X`009case tc_fsubr:
  2186. X`009case tc_msubr:
  2187. X`009  break;
  2188. X`009default:
  2189. X`009  p = get_user_type_hooks(TYPE(ptr));
  2190. X`009  if (p->gc_free) (*p->gc_free)(ptr);`125`125
  2191. X     `032
  2192. Xvoid gc_stop_and_copy(void)
  2193. X`123LISP newspace,oldspace,end;
  2194. X long flag;
  2195. X flag = no_interrupt(1);
  2196. X errjmp_ok = 0;
  2197. X oldspace = heap_org;
  2198. X end = heap;
  2199. X old_heap_used = end - oldspace;
  2200. X newspace = get_newspace();
  2201. X scan_registers();
  2202. X scan_newspace(newspace);
  2203. X free_oldspace(oldspace,end);
  2204. X errjmp_ok = 1;
  2205. X no_interrupt(flag);`125
  2206. X
  2207. Xvoid gc_for_newcell(void)
  2208. X`123long flag;
  2209. X if (errjmp_ok == 0) gc_fatal_error();
  2210. X flag = no_interrupt(1);
  2211. X errjmp_ok = 0;
  2212. X gc_mark_and_sweep();
  2213. X errjmp_ok = 1;
  2214. X no_interrupt(flag);
  2215. X if NULLP(freelist) gc_fatal_error();`125
  2216. X
  2217. Xvoid gc_mark_and_sweep(void)
  2218. X`123LISP stack_end;
  2219. X gc_ms_stats_start();
  2220. X setjmp(save_regs_gc_mark);
  2221. X mark_locations((LISP *) save_regs_gc_mark,
  2222. X`009`009(LISP *) (((char *) save_regs_gc_mark) + sizeof(save_regs_gc_mark)));
  2223. X mark_protected_registers();
  2224. X mark_locations((LISP *) stack_start_ptr,
  2225. X`009`009(LISP *) &stack_end);
  2226. X#ifdef THINK_C
  2227. X mark_locations((LISP *) ((char *) stack_start_ptr + 2),
  2228. X`009`009(LISP *) ((char *) &stack_end + 2));
  2229. X#endif
  2230. X gc_sweep();
  2231. X gc_ms_stats_end();`125
  2232. X
  2233. Xvoid gc_ms_stats_start(void)
  2234. X`123gc_rt = myruntime();
  2235. X gc_cells_collected = 0;
  2236. X if (gc_status_flag)
  2237. X   printf("[starting GC]\n");`125
  2238. X
  2239. Xvoid gc_ms_stats_end(void)
  2240. X`123gc_rt = myruntime() - gc_rt;
  2241. X gc_time_taken = gc_time_taken + gc_rt;
  2242. X if (gc_status_flag)
  2243. X   printf("[GC took %g cpu seconds, %ld cells collected]\n",
  2244. X`009  gc_rt,
  2245. X`009  gc_cells_collected);`125
  2246. X
  2247. Xvoid gc_mark(LISP ptr)
  2248. X`123struct user_type_hooks *p;
  2249. X gc_mark_loop:
  2250. X if NULLP(ptr) return;
  2251. X if ((*ptr).gc_mark) return;
  2252. X (*ptr).gc_mark = 1;
  2253. X switch ((*ptr).type)
  2254. X   `123case tc_flonum:
  2255. X      break;
  2256. X    case tc_cons:
  2257. X      gc_mark(CAR(ptr));
  2258. X      ptr = CDR(ptr);
  2259. X      goto gc_mark_loop;
  2260. X    case tc_symbol:
  2261. X      ptr = VCELL(ptr);
  2262. X      goto gc_mark_loop;
  2263. X    case tc_closure:
  2264. X      gc_mark((*ptr).storage_as.closure.code);
  2265. X      ptr = (*ptr).storage_as.closure.env;
  2266. X      goto gc_mark_loop;
  2267. X    case tc_subr_0:
  2268. X    case tc_subr_1:
  2269. X    case tc_subr_2:
  2270. X    case tc_subr_3:
  2271. X    case tc_lsubr:
  2272. X    case tc_fsubr:
  2273. X    case tc_msubr:
  2274. X      break;
  2275. X    default:
  2276. X      p = get_user_type_hooks(TYPE(ptr));
  2277. X      if (p->gc_mark)
  2278. X`009ptr = (*p->gc_mark)(ptr);`125`125
  2279. X
  2280. Xvoid mark_protected_registers(void)
  2281. X`123struct gc_protected *reg;
  2282. X LISP *location;
  2283. X long j,n;
  2284. X for(reg = protected_registers; reg; reg = (*reg).next)
  2285. X   `123location = (*reg).location;
  2286. X    n = (*reg).length;
  2287. X    for(j=0;j<n;++j)
  2288. X      gc_mark(location[j]);`125`125
  2289. X
  2290. Xvoid mark_locations(LISP *start,LISP *end)
  2291. X`123LISP *tmp;
  2292. X long n;
  2293. X if (start > end)
  2294. X   `123tmp = start;
  2295. X    start = end;
  2296. X    end = tmp;`125
  2297. X n = end - start;
  2298. X mark_locations_array(start,n);`125
  2299. X
  2300. Xvoid mark_locations_array(LISP *x,long n)
  2301. X`123int j;
  2302. X LISP p;
  2303. X for(j=0;j<n;++j)
  2304. X   `123p = x[j];
  2305. X    if ((p >= heap_org) &&
  2306. X`009(p < heap_end) &&
  2307. X`009(((((char *)p) - ((char *)heap_org)) % sizeof(struct obj)) == 0) &&
  2308. X`009NTYPEP(p,tc_free_cell))
  2309. X      gc_mark(p);`125`125
  2310. X
  2311. Xvoid gc_sweep(void)
  2312. X`123LISP ptr,end,nfreelist;
  2313. X long n;
  2314. X struct user_type_hooks *p;
  2315. X end = heap_end;
  2316. X n = 0;
  2317. X nfreelist = freelist;
  2318. X for(ptr=heap_org; ptr < end; ++ptr)
  2319. X   if (((*ptr).gc_mark == 0))
  2320. X     `123switch((*ptr).type)
  2321. X`009`123case tc_free_cell:
  2322. X`009 case tc_cons:
  2323. X`009 case tc_closure:
  2324. X`009 case tc_symbol:
  2325. X`009 case tc_flonum:
  2326. X`009 case tc_subr_0:
  2327. X`009 case tc_subr_1:
  2328. X`009 case tc_subr_2:
  2329. X`009 case tc_subr_3:
  2330. X`009 case tc_lsubr:
  2331. X`009 case tc_fsubr:
  2332. X`009 case tc_msubr:
  2333. X`009   break;
  2334. X`009 default:
  2335. X`009   p = get_user_type_hooks(TYPE(ptr));
  2336. X`009   if (p->gc_free)
  2337. X`009     (*p->gc_free)(ptr);`125
  2338. X      ++n;
  2339. X      (*ptr).type = tc_free_cell;
  2340. X      CDR(ptr) = nfreelist;
  2341. X      nfreelist = ptr;`125
  2342. X   else
  2343. X     (*ptr).gc_mark = 0;
  2344. X gc_cells_collected = n;
  2345. X freelist = nfreelist;`125
  2346. X
  2347. XLISP user_gc(LISP args)
  2348. X`123long old_status_flag,flag;
  2349. X if (gc_kind_copying == 1)
  2350. X   err("implementation cannot GC at will with stop-and-copy\n",
  2351. X       NIL);
  2352. X flag = no_interrupt(1);
  2353. X errjmp_ok = 0;
  2354. X old_status_flag = gc_status_flag;
  2355. X if NNULLP(args)
  2356. X   if NULLP(car(args)) gc_status_flag = 0; else gc_status_flag = 1;
  2357. X gc_mark_and_sweep();
  2358. X gc_status_flag = old_status_flag;
  2359. X errjmp_ok = 1;
  2360. X no_interrupt(flag);
  2361. X return(NIL);`125
  2362. X`032
  2363. XLISP gc_status(LISP args)
  2364. X`123LISP l;
  2365. X int n;
  2366. X if NNULLP(args)`032
  2367. X   if NULLP(car(args)) gc_status_flag = 0; else gc_status_flag = 1;
  2368. X if (gc_kind_copying == 1)
  2369. X   `123if (gc_status_flag)
  2370. X      put_st("garbage collection is on\n");
  2371. X   else
  2372. X     put_st("garbage collection is off\n");
  2373. X    sprintf(tkbuffer,"%ld allocated %ld free\n",
  2374. X`009    heap - heap_org, heap_end - heap);
  2375. X    put_st(tkbuffer);`125
  2376. X else
  2377. X   `123if (gc_status_flag)
  2378. X      put_st("garbage collection verbose\n");
  2379. X    else
  2380. X      put_st("garbage collection silent\n");
  2381. X    `123for(n=0,l=freelist;NNULLP(l); ++n) l = CDR(l);
  2382. X     sprintf(tkbuffer,"%ld allocated %ld free\n",
  2383. X`009     (heap_end - heap_org) - n,n);
  2384. X     put_st(tkbuffer);`125`125
  2385. X return(NIL);`125
  2386. X
  2387. XLISP leval_args(LISP l,LISP env)
  2388. X`123LISP result,v1,v2,tmp;
  2389. X if NULLP(l) return(NIL);
  2390. X if NCONSP(l) err("bad syntax argument list",l);
  2391. X result = cons(leval(CAR(l),env),NIL);
  2392. X for(v1=result,v2=CDR(l);
  2393. X     CONSP(v2);
  2394. X     v1 = tmp, v2 = CDR(v2))
  2395. X  `123tmp = cons(leval(CAR(v2),env),NIL);
  2396. X   CDR(v1) = tmp;`125
  2397. X if NNULLP(v2) err("bad syntax argument list",l);
  2398. X return(result);`125
  2399. X
  2400. XLISP extend_env(LISP actuals,LISP formals,LISP env)
  2401. X`123if SYMBOLP(formals)
  2402. X   return(cons(cons(cons(formals,NIL),cons(actuals,NIL)),env));
  2403. X return(cons(cons(formals,actuals),env));`125
  2404. X
  2405. XLISP envlookup(LISP var,LISP env)
  2406. X`123LISP frame,al,fl,tmp;
  2407. X for(frame=env;CONSP(frame);frame=CDR(frame))
  2408. X   `123tmp = CAR(frame);
  2409. X    if NCONSP(tmp) err("damaged frame",tmp);
  2410. X    for(fl=CAR(tmp),al=CDR(tmp);
  2411. X`009CONSP(fl);
  2412. X`009fl=CDR(fl),al=CDR(al))
  2413. X      `123if NCONSP(al) err("too few arguments",tmp);
  2414. X       if EQ(CAR(fl),var) return(al);`125`125
  2415. X if NNULLP(frame) err("damaged env",env);
  2416. X return(NIL);`125
  2417. X
  2418. Xvoid set_eval_hooks(long type,LISP (*fcn)())
  2419. X`123struct user_type_hooks *p;
  2420. X p = get_user_type_hooks(type);
  2421. X p->leval = fcn;`125
  2422. X
  2423. XLISP leval(LISP x,LISP env)
  2424. X`123LISP tmp,arg1;
  2425. X struct user_type_hooks *p;
  2426. X STACK_CHECK(&x);
  2427. X loop:
  2428. X INTERRUPT_CHECK();
  2429. X switch TYPE(x)
  2430. X   `123case tc_symbol:
  2431. X      tmp = envlookup(x,env);
  2432. X      if NNULLP(tmp) return(CAR(tmp));
  2433. X      tmp = VCELL(x);
  2434. X      if EQ(tmp,unbound_marker) err("unbound variable",x);
  2435. X      return(tmp);
  2436. X    case tc_cons:
  2437. X      tmp = CAR(x);
  2438. X      switch TYPE(tmp)
  2439. X`009`123case tc_symbol:
  2440. X`009   tmp = envlookup(tmp,env);
  2441. X`009   if NNULLP(tmp)
  2442. X`009     `123tmp = CAR(tmp);
  2443. X`009      break;`125
  2444. X`009   tmp = VCELL(CAR(x));
  2445. X`009   if EQ(tmp,unbound_marker) err("unbound variable",CAR(x));
  2446. X`009   break;
  2447. X`009 case tc_cons:
  2448. X`009   tmp = leval(tmp,env);
  2449. X`009   break;`125
  2450. X      switch TYPE(tmp)
  2451. X`009`123case tc_subr_0:
  2452. X`009   return(SUBRF(tmp)());
  2453. X`009 case tc_subr_1:
  2454. X`009   return(SUBRF(tmp)(leval(car(CDR(x)),env)));
  2455. X`009 case tc_subr_2:
  2456. X`009   x = CDR(x);
  2457. X`009   arg1 = leval(car(x),env);
  2458. X`009   x = NULLP(x) ? NIL : CDR(x);
  2459. X`009   return(SUBRF(tmp)(arg1,
  2460. X`009`009`009     leval(car(x),env)));
  2461. X`009 case tc_subr_3:
  2462. X`009   x = CDR(x);
  2463. X`009   arg1 = leval(car(x),env);
  2464. X`009   x = NULLP(x) ? NIL : CDR(x);
  2465. X`009   return(SUBRF(tmp)(arg1,
  2466. X`009`009`009     leval(car(x),env),
  2467. X`009`009`009     leval(car(cdr(x)),env)));
  2468. X`009 case tc_lsubr:
  2469. X`009   return(SUBRF(tmp)(leval_args(CDR(x),env)));
  2470. X`009 case tc_fsubr:
  2471. X`009   return(SUBRF(tmp)(CDR(x),env));
  2472. X`009 case tc_msubr:
  2473. X`009   if NULLP(SUBRF(tmp)(&x,&env)) return(x);
  2474. X`009   goto loop;
  2475. X`009 case tc_closure:
  2476. X`009   env = extend_env(leval_args(CDR(x),env),
  2477. X`009`009`009    car((*tmp).storage_as.closure.code),
  2478. X`009`009`009    (*tmp).storage_as.closure.env);
  2479. X`009   x = cdr((*tmp).storage_as.closure.code);
  2480. X`009   goto loop;
  2481. X`009 case tc_symbol:
  2482. X`009   x = cons(tmp,cons(cons(sym_quote,cons(x,NIL)),NIL));
  2483. X`009   x = leval(x,NIL);
  2484. X`009   goto loop;
  2485. X`009 default:
  2486. X`009   p = get_user_type_hooks(TYPE(tmp));
  2487. X`009   if (p->leval)
  2488. V`009     `123if NULLP((*p->leval)(tmp,&x,&env)) return(x); else goto loop;`12
  2489. X5
  2490. X`009   err("bad function",tmp);`125
  2491. X    default:
  2492. X      return(x);`125`125
  2493. X
  2494. XLISP setvar(LISP var,LISP val,LISP env)
  2495. X`123LISP tmp;
  2496. X if NSYMBOLP(var) err("wta(non-symbol) to setvar",var);
  2497. X tmp = envlookup(var,env);
  2498. X if NULLP(tmp) return(VCELL(var) = val);
  2499. X return(CAR(tmp)=val);`125
  2500. X`032
  2501. XLISP leval_setq(LISP args,LISP env)
  2502. X`123return(setvar(car(args),leval(car(cdr(args)),env),env));`125
  2503. X
  2504. XLISP syntax_define(LISP args)
  2505. X`123if SYMBOLP(car(args)) return(args);
  2506. X return(syntax_define(
  2507. X        cons(car(car(args)),
  2508. X`009cons(cons(sym_lambda,
  2509. X`009     cons(cdr(car(args)),
  2510. X`009`009  cdr(args))),
  2511. X`009     NIL))));`125
  2512. X     `032
  2513. XLISP leval_define(LISP args,LISP env)
  2514. X`123LISP tmp,var,val;
  2515. X tmp = syntax_define(args);
  2516. X var = car(tmp);
  2517. X if NSYMBOLP(var) err("wta(non-symbol) to define",var);
  2518. X val = leval(car(cdr(tmp)),env);
  2519. X tmp = envlookup(var,env);
  2520. X if NNULLP(tmp) return(CAR(tmp) = val);
  2521. X if NULLP(env) return(VCELL(var) = val);
  2522. X tmp = car(env);
  2523. X setcar(tmp,cons(var,car(tmp)));
  2524. X setcdr(tmp,cons(val,cdr(tmp)));
  2525. X return(val);`125
  2526. X`032
  2527. XLISP leval_if(LISP *pform,LISP *penv)
  2528. X`123LISP args,env;
  2529. X args = cdr(*pform);
  2530. X env = *penv;
  2531. X if NNULLP(leval(car(args),env))`032
  2532. X    *pform = car(cdr(args)); else *pform = car(cdr(cdr(args)));
  2533. X return(truth);`125
  2534. X
  2535. XLISP leval_lambda(LISP args,LISP env)
  2536. X`123LISP body;
  2537. X if NULLP(cdr(cdr(args)))
  2538. X   body = car(cdr(args));
  2539. X  else body = cons(sym_progn,cdr(args));
  2540. X return(closure(env,cons(arglchk(car(args)),body)));`125
  2541. X                        `032
  2542. XLISP leval_progn(LISP *pform,LISP *penv)
  2543. X`123LISP env,l,next;
  2544. X env = *penv;
  2545. X l = cdr(*pform);
  2546. X next = cdr(l);
  2547. X while(NNULLP(next)) `123leval(car(l),env);l=next;next=cdr(next);`125
  2548. X *pform = car(l);`032
  2549. X return(truth);`125
  2550. X
  2551. XLISP leval_or(LISP *pform,LISP *penv)
  2552. X`123LISP env,l,next,val;
  2553. X env = *penv;
  2554. X l = cdr(*pform);
  2555. X next = cdr(l);
  2556. X while(NNULLP(next))
  2557. X   `123val = leval(car(l),env);
  2558. X    if NNULLP(val) `123*pform = val; return(NIL);`125
  2559. X    l=next;next=cdr(next);`125
  2560. X *pform = car(l);`032
  2561. X return(truth);`125
  2562. X
  2563. XLISP leval_and(LISP *pform,LISP *penv)
  2564. X`123LISP env,l,next;
  2565. X env = *penv;
  2566. X l = cdr(*pform);
  2567. X if NULLP(l) `123*pform = truth; return(NIL);`125
  2568. X next = cdr(l);
  2569. X while(NNULLP(next))
  2570. X   `123if NULLP(leval(car(l),env)) `123*pform = NIL; return(NIL);`125
  2571. X    l=next;next=cdr(next);`125
  2572. X *pform = car(l);`032
  2573. X return(truth);`125
  2574. X
  2575. XLISP leval_catch(LISP args,LISP env)
  2576. X`123struct catch_frame frame;
  2577. X int k;
  2578. X LISP l,val;
  2579. X frame.tag = leval(car(args),env);
  2580. X frame.next = catch_framep;
  2581. X k = setjmp(frame.cframe);
  2582. X catch_framep = &frame;
  2583. X if (k == 2)
  2584. X   `123catch_framep = frame.next;
  2585. X    return(frame.retval);`125
  2586. X for(l=cdr(args); NNULLP(l); l = cdr(l))
  2587. X   val = leval(car(l),env);
  2588. X catch_framep = frame.next;
  2589. X return(val);`125
  2590. X
  2591. XLISP lthrow(LISP tag,LISP value)
  2592. X`123struct catch_frame *l;
  2593. X for(l=catch_framep; l; l = (*l).next)
  2594. X   if EQ((*l).tag,tag)
  2595. X     `123(*l).retval = value;
  2596. X      longjmp((*l).cframe,2);`125
  2597. X err("no *catch found with this tag",tag);
  2598. X return(NIL);`125
  2599. X
  2600. XLISP leval_let(LISP *pform,LISP *penv)
  2601. X`123LISP env,l;
  2602. X l = cdr(*pform);
  2603. X env = *penv;
  2604. X *penv = extend_env(leval_args(car(cdr(l)),env),car(l),env);
  2605. X *pform = car(cdr(cdr(l)));
  2606. X return(truth);`125
  2607. X
  2608. XLISP reverse(LISP l)
  2609. X`123LISP n,p;
  2610. X n = NIL;
  2611. X for(p=l;NNULLP(p);p=cdr(p)) n = cons(car(p),n);
  2612. X return(n);`125
  2613. X
  2614. XLISP let_macro(LISP form)
  2615. X`123LISP p,fl,al,tmp;
  2616. X fl = NIL;
  2617. X al = NIL;
  2618. X for(p=car(cdr(form));NNULLP(p);p=cdr(p))
  2619. X  `123tmp = car(p);
  2620. X   if SYMBOLP(tmp) `123fl = cons(tmp,fl); al = cons(NIL,al);`125
  2621. X   else `123fl = cons(car(tmp),fl); al = cons(car(cdr(tmp)),al);`125`125
  2622. X p = cdr(cdr(form));
  2623. X if NULLP(cdr(p)) p = car(p); else p = cons(sym_progn,p);
  2624. X setcdr(form,cons(reverse(fl),cons(reverse(al),cons(p,NIL))));
  2625. X setcar(form,cintern("let-internal"));
  2626. X return(form);`125
  2627. X  `032
  2628. XLISP leval_quote(LISP args,LISP env)
  2629. X`123return(car(args));`125
  2630. X
  2631. XLISP leval_tenv(LISP args,LISP env)
  2632. X`123return(env);`125
  2633. X
  2634. XLISP leval_while(LISP args,LISP env)
  2635. X`123LISP l;
  2636. X while NNULLP(leval(car(args),env))
  2637. X   for(l=cdr(args);NNULLP(l);l=cdr(l))
  2638. X     leval(car(l),env);
  2639. X return(NIL);`125
  2640. X
  2641. XLISP symbolconc(LISP args)
  2642. X`123long size;
  2643. X LISP l,s;
  2644. X size = 0;
  2645. X tkbuffer[0] = 0;
  2646. X for(l=args;NNULLP(l);l=cdr(l))
  2647. X   `123s = car(l);
  2648. X    if NSYMBOLP(s) err("wta(non-symbol) to symbolconc",s);
  2649. X    size = size + strlen(PNAME(s));
  2650. X    if (size >  TKBUFFERN) err("symbolconc buffer overflow",NIL);
  2651. X    strcat(tkbuffer,PNAME(s));`125
  2652. X return(rintern(tkbuffer));`125
  2653. X
  2654. Xvoid set_print_hooks(long type,void (*fcn)())
  2655. X`123struct user_type_hooks *p;
  2656. X p = get_user_type_hooks(type);
  2657. X p->prin1 = fcn;`125
  2658. X
  2659. XLISP lprin1f(LISP exp,FILE *f)
  2660. X`123LISP tmp;
  2661. X struct user_type_hooks *p;
  2662. X STACK_CHECK(&exp);
  2663. X INTERRUPT_CHECK();
  2664. X switch TYPE(exp)
  2665. X   `123case tc_nil:
  2666. X      fput_st(f,"()");
  2667. X      break;
  2668. X   case tc_cons:
  2669. X      fput_st(f,"(");
  2670. X      lprin1f(car(exp),f);
  2671. X      for(tmp=cdr(exp);CONSP(tmp);tmp=cdr(tmp))
  2672. X`009`123fput_st(f," ");lprin1f(car(tmp),f);`125
  2673. X      if NNULLP(tmp) `123fput_st(f," . ");lprin1f(tmp,f);`125
  2674. X      fput_st(f,")");
  2675. X      break;
  2676. X    case tc_flonum:
  2677. X      sprintf(tkbuffer,"%g",FLONM(exp));
  2678. X      fput_st(f,tkbuffer);
  2679. X      break;
  2680. X    case tc_symbol:
  2681. X      fput_st(f,PNAME(exp));
  2682. X      break;
  2683. X    case tc_subr_0:
  2684. X    case tc_subr_1:
  2685. X    case tc_subr_2:
  2686. X    case tc_subr_3:
  2687. X    case tc_lsubr:
  2688. X    case tc_fsubr:
  2689. X    case tc_msubr:
  2690. X      sprintf(tkbuffer,"#<SUBR(%d) ",TYPE(exp));
  2691. X      fput_st(f,tkbuffer);
  2692. X      fput_st(f,(*exp).storage_as.subr.name);
  2693. X      fput_st(f,">");
  2694. X      break;
  2695. X    case tc_closure:
  2696. X      fput_st(f,"#<CLOSURE ");
  2697. X      lprin1f(car((*exp).storage_as.closure.code),f);
  2698. X      fput_st(f," ");
  2699. X      lprin1f(cdr((*exp).storage_as.closure.code),f);
  2700. X      fput_st(f,">");
  2701. X      break;
  2702. X    default:
  2703. X      p = get_user_type_hooks(TYPE(exp));
  2704. X      if (p->prin1)
  2705. X`009(*p->prin1)(exp,f);
  2706. X      else
  2707. X`009`123sprintf(tkbuffer,"#<UNKNOWN %d %lX>",TYPE(exp),exp);
  2708. X`009 fput_st(f,tkbuffer);`125`125
  2709. X return(NIL);`125
  2710. X
  2711. XLISP lprint(LISP exp)
  2712. X`123lprin1f(exp,stdout);
  2713. X put_st("\n");
  2714. X return(NIL);`125
  2715. X
  2716. XLISP lread(void)
  2717. X`123return(lreadf(stdin));`125
  2718. X
  2719. Xint f_getc(FILE *f)
  2720. X`123long iflag,dflag;
  2721. X int c;
  2722. X iflag = no_interrupt(1);
  2723. X dflag = interrupt_differed;
  2724. X c = getc(f);
  2725. X#ifdef VMS
  2726. X if ((dflag == 0) & interrupt_differed & (f == stdin))
  2727. X   while((c != 0) & (c != EOF)) c = getc(f);
  2728. X#endif
  2729. X no_interrupt(iflag);
  2730. X return(c);`125
  2731. X
  2732. Xvoid f_ungetc(int c, FILE *f)
  2733. X`123ungetc(c,f);`125
  2734. X
  2735. Xint flush_ws(struct gen_readio *f,char *eoferr)
  2736. X`123int c,commentp;
  2737. X commentp = 0;
  2738. X while(1)
  2739. X   `123c = GETC_FCN(f);
  2740. X    if (c == EOF) if (eoferr) err(eoferr,NIL); else return(c);
  2741. X    if (commentp) `123if (c == '\n') commentp = 0;`125
  2742. X    else if (c == ';') commentp = 1;
  2743. X    else if (!isspace(c)) return(c);`125`125
  2744. X
  2745. XLISP lreadf(FILE *f)
  2746. X`123struct gen_readio s;
  2747. X s.getc_fcn = (int (*)(char *))f_getc;
  2748. X s.ungetc_fcn = (void (*)(int, char *))f_ungetc;
  2749. X s.cb_argument = (char *) f;
  2750. X return(readtl(&s));`125
  2751. X
  2752. XLISP readtl(struct gen_readio *f)
  2753. X`123int c;
  2754. X c = flush_ws(f,(char *)NULL);
  2755. X if (c == EOF) return(eof_val);
  2756. X UNGETC_FCN(c,f);
  2757. X return(lreadr(f));`125
  2758. X`032
  2759. Xvoid set_read_hooks(char *all_set,char *end_set,
  2760. X`009`009    LISP (*fcn1)(),LISP (*fcn2)())
  2761. X`123user_ch_readm = all_set;
  2762. X user_te_readm = end_set;
  2763. X user_readm = fcn1;
  2764. X user_readt = fcn2;`125
  2765. X
  2766. XLISP lreadr(struct gen_readio *f)
  2767. X`123int c,j;
  2768. X char *p;
  2769. X STACK_CHECK(&f);
  2770. X p = tkbuffer;
  2771. X c = flush_ws(f,"end of file inside read");
  2772. X switch (c)
  2773. X   `123case '(':
  2774. X      return(lreadparen(f));
  2775. X    case ')':
  2776. X      err("unexpected close paren",NIL);
  2777. X    case '\'':
  2778. X      return(cons(sym_quote,cons(lreadr(f),NIL)));
  2779. X    case '`096':
  2780. X      return(cons(cintern("+internal-backquote"),lreadr(f)));
  2781. X    case ',':
  2782. X      c = GETC_FCN(f);
  2783. X      switch(c)
  2784. X`009`123case '@':
  2785. X`009   p = "+internal-comma-atsign";
  2786. X`009   break;
  2787. X`009 case '.':
  2788. X`009   p = "+internal-comma-dot";
  2789. X`009   break;
  2790. X`009 default:
  2791. X`009   p = "+internal-comma";
  2792. X`009   UNGETC_FCN(c,f);`125
  2793. X      return(cons(cintern(p),lreadr(f)));
  2794. X    case '"':
  2795. X      return(lreadstring(f));
  2796. X    default:
  2797. X      if ((user_readm != NULL) && strchr(user_ch_readm,c))
  2798. X`009return((*user_readm)(c,f));`125
  2799. X *p++ = c;
  2800. X for(j = 1; j<TKBUFFERN; ++j)
  2801. X   `123c = GETC_FCN(f);
  2802. X    if (c == EOF) return(lreadtk(j));
  2803. X    if (isspace(c)) return(lreadtk(j));
  2804. X    if (strchr("()'`096,;\"",c) `124`124 strchr(user_te_readm,c))
  2805. X      `123UNGETC_FCN(c,f);return(lreadtk(j));`125
  2806. X    *p++ = c;`125
  2807. X err("token larger than TKBUFFERN",NIL);`125
  2808. X
  2809. XLISP lreadparen(struct gen_readio *f)
  2810. X`123int c;
  2811. X LISP tmp;
  2812. X c = flush_ws(f,"end of file inside list");
  2813. X if (c == ')') return(NIL);
  2814. X UNGETC_FCN(c,f);
  2815. X tmp = lreadr(f);
  2816. X if EQ(tmp,sym_dot)
  2817. X   `123tmp = lreadr(f);
  2818. X    c = flush_ws(f,"end of file inside list");
  2819. X    if (c != ')') err("missing close paren",NIL);
  2820. X    return(tmp);`125
  2821. X return(cons(tmp,lreadparen(f)));`125
  2822. X
  2823. XLISP lreadtk(long j)
  2824. X`123int k,flag;
  2825. X char c,*p;
  2826. X LISP tmp;
  2827. X int adigit;
  2828. X p = tkbuffer;
  2829. X p[j] = 0;
  2830. X if (user_readt != NULL)
  2831. X   `123tmp = (*user_readt)(p,j,&flag);
  2832. X    if (flag) return(tmp);`125
  2833. X if (*p == '-') p+=1;
  2834. X adigit = 0;
  2835. X while(isdigit(*p)) `123p+=1; adigit=1;`125
  2836. X if (*p=='.')
  2837. X   `123p += 1;
  2838. X    while(isdigit(*p)) `123p+=1; adigit=1;`125`125
  2839. X if (!adigit) goto a_symbol;
  2840. X if (*p=='e')
  2841. X   `123p+=1;
  2842. X    if (*p=='-'`124`124*p=='+') p+=1;
  2843. X    if (!isdigit(*p)) goto a_symbol; else p+=1;
  2844. X    while(isdigit(*p)) p+=1;`125
  2845. X if (*p) goto a_symbol;
  2846. X return(flocons(atof(tkbuffer)));
  2847. X a_symbol:
  2848. X return(rintern(tkbuffer));`125
  2849. X     `032
  2850. XLISP copy_list(LISP x)
  2851. X`123if NULLP(x) return(NIL);
  2852. X STACK_CHECK(&x);
  2853. X return(cons(car(x),copy_list(cdr(x))));`125
  2854. X
  2855. XLISP oblistfn(void)
  2856. X`123return(copy_list(oblistvar));`125
  2857. X
  2858. Xvoid close_open_files(void)
  2859. X`123LISP l,p;
  2860. X for(l=open_files;NNULLP(l);l=cdr(l))
  2861. X   `123p = car(l);
  2862. X    if (p->storage_as.c_file.f)
  2863. X      `123printf("closing a file left open: %s\n",
  2864. X`009      (p->storage_as.c_file.name) ? p->storage_as.c_file.name : "");
  2865. X       file_gc_free(p);`125`125
  2866. X open_files = NIL;`125
  2867. X
  2868. XLISP fopen_c(char *name,char *how)
  2869. X`123LISP sym;
  2870. X long flag;
  2871. X flag = no_interrupt(1);
  2872. X sym = newcell(tc_c_file);
  2873. X sym->storage_as.c_file.f = (FILE *)NULL;
  2874. X sym->storage_as.c_file.name = (char *)NULL;
  2875. X open_files = cons(sym,open_files);
  2876. X if (!(sym->storage_as.c_file.f = fopen(name,how)))
  2877. X   `123perror(name);
  2878. X    put_st("\n");
  2879. X    err("could not open file",NIL);`125
  2880. X sym->storage_as.c_file.name = (char *) must_malloc(strlen(name)+1);
  2881. X strcpy(sym->storage_as.c_file.name,name);
  2882. X no_interrupt(flag);
  2883. X return(sym);`125
  2884. X
  2885. XLISP fopen_l(LISP name,LISP how)
  2886. V`123return(fopen_c(get_c_string(name),NULLP(how) ? "r" : get_c_string(how)));
  2887. X`125
  2888. X
  2889. XLISP delq(LISP elem,LISP l)
  2890. X`123if NULLP(l) return(l);
  2891. X STACK_CHECK(&elem);
  2892. X if EQ(elem,car(l)) return(cdr(l));
  2893. X setcdr(l,delq(elem,cdr(l)));
  2894. X return(l);`125
  2895. X
  2896. XLISP fclose_l(LISP p)
  2897. X`123long flag;
  2898. X flag = no_interrupt(1);
  2899. X if NTYPEP(p,tc_c_file) err("not a file",p);
  2900. X file_gc_free(p);
  2901. X open_files = delq(p,open_files);
  2902. X no_interrupt(flag);
  2903. X return(NIL);`125
  2904. X
  2905. XLISP vload(char *fname,long cflag)
  2906. X`123LISP form,result,tail,lf;
  2907. X FILE *f;
  2908. X put_st("loading ");
  2909. X put_st(fname);
  2910. X put_st("\n");
  2911. X lf = fopen_c(fname,"r");
  2912. X f = lf->storage_as.c_file.f;
  2913. X result = NIL;
  2914. X tail = NIL;
  2915. X while(1)
  2916. X   `123form = lreadf(f);
  2917. X    if EQ(form,eof_val) break;
  2918. X    if (cflag)
  2919. X      `123form = cons(form,NIL);
  2920. X       if NULLP(result)
  2921. X`009 result = tail = form;
  2922. X       else
  2923. X`009 tail = setcdr(tail,form);`125
  2924. X    else
  2925. X      leval(form,NIL);`125
  2926. X fclose_l(lf);
  2927. X put_st("done.\n");
  2928. X return(result);`125
  2929. X
  2930. XLISP load(LISP fname,LISP cflag)
  2931. X`123return(vload(get_c_string(fname),NULLP(cflag) ? 0 : 1));`125
  2932. X
  2933. XLISP save_forms(LISP fname,LISP forms,LISP how)
  2934. X`123char *cname,*chow;
  2935. X LISP l,lf;
  2936. X FILE *f;
  2937. X cname = get_c_string(fname);
  2938. X if EQ(how,NIL) chow = "w";
  2939. X else if EQ(how,cintern("a")) chow = "a";
  2940. X else err("bad argument to save-forms",how);
  2941. X put_st((*chow == 'a') ? "appending" : "saving");
  2942. X put_st(" forms to ");
  2943. X put_st(cname);
  2944. X put_st("\n");
  2945. X lf = fopen_c(cname,chow);
  2946. X f = lf->storage_as.c_file.f;
  2947. X for(l=forms;NNULLP(l);l=cdr(l))
  2948. X   `123lprin1f(car(l),f);
  2949. X    putc('\n',f);`125
  2950. X fclose_l(lf);
  2951. X put_st("done.\n");
  2952. X return(truth);`125
  2953. X
  2954. XLISP quit(void)
  2955. X`123longjmp(errjmp,2);
  2956. X return(NIL);`125
  2957. X
  2958. XLISP nullp(LISP x)
  2959. X`123if EQ(x,NIL) return(truth); else return(NIL);`125
  2960. X
  2961. XLISP arglchk(LISP x)
  2962. X`123LISP l;
  2963. X if SYMBOLP(x) return(x);
  2964. X for(l=x;CONSP(l);l=CDR(l));
  2965. X if NNULLP(l) err("improper formal argument list",x);
  2966. X return(x);`125
  2967. X
  2968. Xvoid file_gc_free(LISP ptr)
  2969. X`123if (ptr->storage_as.c_file.f)
  2970. X   `123fclose(ptr->storage_as.c_file.f);
  2971. X    ptr->storage_as.c_file.f = (FILE *) NULL;`125
  2972. X if (ptr->storage_as.c_file.name)
  2973. X   `123free(ptr->storage_as.c_file.name);
  2974. X    ptr->storage_as.c_file.name = NULL;`125`125
  2975. X  `032
  2976. Xvoid file_prin1(LISP ptr,FILE *f)
  2977. X`123char *name;
  2978. X name = ptr->storage_as.c_file.name;
  2979. X fput_st(f,"#<FILE ");
  2980. X sprintf(tkbuffer," %lX",ptr->storage_as.c_file.f);
  2981. X fput_st(f,tkbuffer);
  2982. X if (name)
  2983. X   `123fput_st(f," ");
  2984. X    fput_st(f,name);`125
  2985. X fput_st(f,">");`125
  2986. X
  2987. XFILE *get_c_file(LISP p,FILE *deflt)
  2988. X`123if (NULLP(p) && deflt) return(deflt);
  2989. X if NTYPEP(p,tc_c_file) err("not a file",p);
  2990. X if (!p->storage_as.c_file.f) err("file is closed",p);
  2991. X return(p->storage_as.c_file.f);`125
  2992. X
  2993. XLISP lgetc(LISP p)
  2994. X`123int i;
  2995. X i = f_getc(get_c_file(p,stdin));
  2996. X return((i == EOF) ? NIL : flocons((double)i));`125
  2997. X
  2998. XLISP lputc(LISP c,LISP p)
  2999. X`123long flag;
  3000. X int i;
  3001. X FILE *f;
  3002. X f = get_c_file(p,stdout);
  3003. X if FLONUMP(c)
  3004. X   i = FLONM(c);
  3005. X else
  3006. X   i = *get_c_string(c);
  3007. X flag = no_interrupt(1);
  3008. X putc(i,f);
  3009. X no_interrupt(flag);
  3010. X return(NIL);`125
  3011. X    `032
  3012. XLISP lputs(LISP str,LISP p)
  3013. X`123fput_st(get_c_file(p,stdout),get_c_string(str));
  3014. X return(NIL);`125
  3015. X
  3016. XLISP parse_number(LISP x)
  3017. X`123char *c;
  3018. X c = get_c_string(x);
  3019. X return(flocons(atof(c)));`125
  3020. X
  3021. Xvoid init_subrs(void)
  3022. X`123init_subrs_1();
  3023. X init_subrs_a();`125
  3024. X
  3025. Xvoid init_subrs_1(void)
  3026. X`123init_subr("cons",tc_subr_2,cons);
  3027. X init_subr("car",tc_subr_1,car);
  3028. X init_subr("cdr",tc_subr_1,cdr);
  3029. X init_subr("set-car!",tc_subr_2,setcar);
  3030. X init_subr("set-cdr!",tc_subr_2,setcdr);
  3031. X init_subr("+",tc_subr_2,plus);
  3032. X init_subr("-",tc_subr_2,difference);
  3033. X init_subr("*",tc_subr_2,ltimes);
  3034. X init_subr("/",tc_subr_2,quotient);
  3035. X init_subr(">",tc_subr_2,greaterp);
  3036. X init_subr("<",tc_subr_2,lessp);
  3037. X init_subr("eq?",tc_subr_2,eq);
  3038. X init_subr("eqv?",tc_subr_2,eql);
  3039. X init_subr("assq",tc_subr_2,assq);
  3040. X init_subr("delq",tc_subr_2,delq);
  3041. X init_subr("read",tc_subr_0,lread);
  3042. X init_subr("eof-val",tc_subr_0,get_eof_val);
  3043. X init_subr("print",tc_subr_1,lprint);
  3044. X init_subr("eval",tc_subr_2,leval);
  3045. X init_subr("define",tc_fsubr,leval_define);
  3046. X init_subr("lambda",tc_fsubr,leval_lambda);
  3047. X init_subr("if",tc_msubr,leval_if);
  3048. X init_subr("while",tc_fsubr,leval_while);
  3049. X init_subr("begin",tc_msubr,leval_progn);
  3050. X init_subr("set!",tc_fsubr,leval_setq);
  3051. X init_subr("or",tc_msubr,leval_or);
  3052. X init_subr("and",tc_msubr,leval_and);
  3053. X init_subr("*catch",tc_fsubr,leval_catch);
  3054. X init_subr("*throw",tc_subr_2,lthrow);
  3055. X init_subr("quote",tc_fsubr,leval_quote);
  3056. X init_subr("oblist",tc_subr_0,oblistfn);
  3057. X init_subr("copy-list",tc_subr_1,copy_list);
  3058. X init_subr("gc-status",tc_lsubr,gc_status);
  3059. X init_subr("gc",tc_lsubr,user_gc);
  3060. X init_subr("load",tc_subr_2,load);
  3061. X init_subr("pair?",tc_subr_1,consp);
  3062. X init_subr("symbol?",tc_subr_1,symbolp);
  3063. X init_subr("number?",tc_subr_1,numberp);
  3064. X init_subr("let-internal",tc_msubr,leval_let);
  3065. X init_subr("let-internal-macro",tc_subr_1,let_macro);
  3066. X init_subr("symbol-bound?",tc_subr_2,symbol_boundp);
  3067. X init_subr("symbol-value",tc_subr_2,symbol_value);
  3068. X init_subr("set-symbol-value!",tc_subr_3,setvar);
  3069. X init_subr("the-environment",tc_fsubr,leval_tenv);
  3070. X init_subr("error",tc_subr_2,lerr);
  3071. X init_subr("quit",tc_subr_0,quit);
  3072. X init_subr("not",tc_subr_1,nullp);
  3073. X init_subr("null?",tc_subr_1,nullp);
  3074. X init_subr("env-lookup",tc_subr_2,envlookup);
  3075. X init_subr("reverse",tc_subr_1,reverse);
  3076. X init_subr("symbolconc",tc_lsubr,symbolconc);
  3077. X init_subr("save-forms",tc_subr_3,save_forms);
  3078. X init_subr("fopen",tc_subr_2,fopen_l);
  3079. X init_subr("fclose",tc_subr_1,fclose_l);
  3080. X init_subr("getc",tc_subr_1,lgetc);
  3081. X init_subr("putc",tc_subr_2,lputc);
  3082. X init_subr("puts",tc_subr_2,lputs);
  3083. X init_subr("parse-number",tc_subr_1,parse_number);
  3084. X init_subr("%%stack-limit",tc_subr_2,stack_limit);`125
  3085. X
  3086. X/* err0,pr,prp are convenient to call from the C-language debugger */
  3087. X
  3088. Xvoid err0(void)
  3089. X`123err("0",NIL);`125
  3090. X
  3091. Xvoid pr(LISP p)
  3092. X`123if ((p >= heap_org) &&
  3093. X     (p < heap_end) &&
  3094. X     (((((char *)p) - ((char *)heap_org)) % sizeof(struct obj)) == 0))
  3095. X   lprint(p);
  3096. X else
  3097. X   put_st("invalid\n");`125
  3098. X
  3099. Xvoid prp(LISP *p)
  3100. X`123if (!p) return;
  3101. X pr(*p);`125
  3102. $ GOSUB UNPACK_FILE
  3103.  
  3104. $ FILE_IS = "SIOD.TIM"
  3105. $ CHECKSUM_IS = 654458232
  3106. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3107. XNew timings, SIOD v2.7
  3108. X
  3109. X
  3110. XMake     Model             FIB(5) FIB(10) FIB(15) FIB(20)  20/FIB(20)
  3111. XSUN      ?                 0.00   0.02     0.12   1.17
  3112. XSUN      4/690             0.00   0.00     0.10   1.27
  3113. X
  3114. X
  3115. X
  3116. X
  3117. XHere are some timings taken with version 1.3 of SIOD. The new version 1.5
  3118. Xis slightly faster. If you do timings it is interesting to try it
  3119. Xwith and without the mark-and-sweep GC, and with various heap sizes.
  3120. X
  3121. XPlease report both total and GC times, heap size, and kinds of GC's used
  3122. Xto: GJC@PARADIGM.COM
  3123. X
  3124. XMake     Model             FIB(5) FIB(10) FIB(15) FIB(20)  20/FIB(20)
  3125. XSun      4                  0.00   0.02    0.38     4.2     4.76
  3126. XDIGITAL  8530(VMS)          0.00   0.07    0.78     8.5     2.35
  3127. XSun      3/280              0.00   0.10    0.88     8.5     2.35
  3128. XDIGITAL  VS-3200(VMS)       0.01   0.11    1.28    14.2     1.41
  3129. XSun      3/180              0.02   0.15    1.56    17.5     1.14
  3130. XEncore   Multimax(NS32)     0.02   0.17    1.85    20.5     0.97
  3131. XDIGITAL  VS-2000            0.02   0.30    3.56    39.7     0.50
  3132. XEncore   Multimax(NS16)     0.03   0.33    3.63    40.4     0.49
  3133. XAMIGA    500 LATTICE C      0.00   0.00    5.00    55.0(x)  0.36
  3134. X
  3135. XUnix compilations done with the -O flag. All 68020 machines
  3136. Xwith -f68881. Heap size of 120000 used. Timing done with standard-fib
  3137. Xprocedure in siod.scm using SIOD Version 1.3 (which is slightly slower
  3138. Xthan earlier versions). AMIGA 500 FIB(20) time is extrapolated from
  3139. Xthe FIB(15) time.
  3140. X
  3141. XCheck to be sure that your standard-fib returns the following:
  3142. X
  3143. X n  FIB(n)  Cons Work
  3144. X 5      5      66
  3145. X10     55     795
  3146. X15    610    8877
  3147. X20   6765   98508
  3148. X
  3149. X(Figures above for -n0, no inums)
  3150. $ GOSUB UNPACK_FILE
  3151.  
  3152. $ FILE_IS = "MAKEFILE.COM"
  3153. $ CHECKSUM_IS = 726546442
  3154. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3155. X$ CFLAGS = ""
  3156. X$ LFLAGS = ""
  3157. X$!
  3158. X$ CC'CFLAGS'   SLIB.C
  3159. X$ CC'CFLAGS'   SLIBA.C
  3160. X$ CC'CFLAGS'   SIOD.C
  3161. X$ LINK'LFLAGS' SIOD.OBJ,SLIB.OBJ,SLIBA.OBJ,SYS$INPUT:/OPT
  3162. XSYS$LIBRARY:VAXCRTL/SHARE
  3163. X$ SIOD == "$" + F$ENV("DEFAULT") + "SIOD"
  3164. $ GOSUB UNPACK_FILE
  3165.  
  3166. $ FILE_IS = "PRATT.SCM"
  3167. $ CHECKSUM_IS = 1010490348
  3168. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3169. X;; -*-mode:lisp-*-
  3170. X;;
  3171. V;; A simple Pratt-Parser for SIOD: 2-FEB-90, George Carrette, GJC@PARADIGM.CO
  3172. XM
  3173. X;; Siod version 2.4 may be obtained by anonymous FTP to BU.EDU (128.197.2.6)
  3174. X;; Get the file users/gjc/siod-v2.4-shar
  3175. X;;
  3176. X;;                   COPYRIGHT (c) 1990 BY                      `032
  3177. X;;     PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.
  3178. X;;         See the source file SLIB.C for more information.`032
  3179. X;;
  3180. X;;
  3181. X;; Based on a theory of parsing presented in:                      `032
  3182. X;;                                                                     `032
  3183. X;;  Pratt, Vaughan R., `096`096Top Down Operator Precedence,''        `032
  3184. X;;  ACM Symposium on Principles of Programming Languages        `032
  3185. X;;  Boston, MA; October, 1973.                                  `032
  3186. X;;                                                                     `032
  3187. X
  3188. X;; The following terms may be useful in deciphering this code:
  3189. X
  3190. X;; NUD -- NUll left Denotation (op has nothing to its left (prefix))
  3191. X;; LED -- LEft Denotation      (op has something to left (postfix or infix))
  3192. X
  3193. X;; LBP -- Left Binding Power  (the stickiness to the left)
  3194. X;; RBP -- Right Binding Power (the stickiness to the right)
  3195. X;;
  3196. X;;
  3197. X
  3198. X;; Example calls
  3199. X;;
  3200. X;; (pl '(f [ a ] = a + b / c)) => (= (f a) (+ a (/ b c)))
  3201. X;;
  3202. X;; (pl '(if g [ a COMMA b ] then a > b else k * c + a * b))
  3203. X;;  => (if (g a b) (> a b) (+ (* k c) (* a b)))
  3204. X;;
  3205. X;; Notes:`032
  3206. X;;
  3207. X;;   This code must be used with siod.scm loaded, in siod version 2.3
  3208. X;;
  3209. X;;   For practical use you will want to write some code to
  3210. X;;   break up input into tokens.
  3211. X
  3212. X
  3213. X(defvar *eof* (list '*eof*))
  3214. X
  3215. X;;`032
  3216. X
  3217. X(defun pl (l)
  3218. X  ;; parse a list of tokens
  3219. X  (setq l (append l '($)))
  3220. X  (toplevel-parse (lambda (op arg)
  3221. X`009`009    (cond ((eq op 'peek)
  3222. X`009`009`009   (if l (car l) *eof*))
  3223. X`009`009`009  ((eq op 'get)
  3224. X`009`009`009   (if l (pop l) *eof*))
  3225. X`009`009`009  ((eq op 'unget)
  3226. X`009`009`009   (push arg l))))))
  3227. X
  3228. X(defun peek-token (stream)
  3229. X  (stream 'peek nil))
  3230. X
  3231. X(defun read-token (stream)
  3232. X  (stream 'get nil))
  3233. X
  3234. X(defun unread-token (x stream)
  3235. X  (stream 'unget x))
  3236. X
  3237. X(defun toplevel-parse (stream)
  3238. X  (if (eq *eof* (peek-token stream))
  3239. X      (read-token stream)
  3240. X    (parse -1 stream)))
  3241. X
  3242. X(defun value-if-symbol (x)
  3243. X  (if (symbol? x)
  3244. X      (symbol-value x)
  3245. X    x))
  3246. X
  3247. X(defun nudcall (token stream)
  3248. X  (if (symbol? token)
  3249. X      (if (get token 'nud)
  3250. X`009  ((value-if-symbol (get token 'nud)) token stream)
  3251. X`009(if (get token 'led)
  3252. X`009    (error 'not-a-prefix-operator token)
  3253. X`009  token)
  3254. X`009token)
  3255. X    token))
  3256. X
  3257. X(defun ledcall (token left stream)
  3258. X  ((value-if-symbol (or (and (symbol? token)
  3259. X`009`009`009     (get token 'led))
  3260. X`009`009`009(error 'not-an-infix-operator token)))
  3261. X   token
  3262. X   left
  3263. X   stream))
  3264. X
  3265. X
  3266. X(defun lbp (token)
  3267. X  (or (and (symbol? token) (get token 'lbp))
  3268. X      200))
  3269. X
  3270. X(defun rbp (token)
  3271. X  (or (and (symbol? token) (get token 'rbp))
  3272. X      200))
  3273. X
  3274. X(defvar *parse-debug* nil)
  3275. X
  3276. X(defun parse (rbp-level stream)
  3277. X  (if *parse-debug* (print `096(parse ,rbp-level)))
  3278. X  (defun parse-loop (translation)
  3279. X    (if (< rbp-level (lbp (peek-token stream)))
  3280. X`009(parse-loop (ledcall (read-token stream) translation stream))
  3281. X      (begin (if *parse-debug* (print translation))
  3282. X`009     translation)))
  3283. X  (parse-loop (nudcall (read-token stream) stream)))
  3284. X
  3285. X(defun header (token)
  3286. X  (or (get token 'header) token))
  3287. X
  3288. X(defun parse-prefix (token stream)
  3289. X  (list (header token)
  3290. X`009(parse (rbp token) stream)))
  3291. X
  3292. X(defun parse-infix (token left stream)
  3293. X  (list (header token)
  3294. X`009left
  3295. X`009(parse (rbp token) stream)))
  3296. X
  3297. X(defun parse-nary (token left stream)
  3298. X  (cons (header token) (cons left (prsnary token stream))))
  3299. X
  3300. X(defun parse-matchfix (token left stream)
  3301. X  (cons (header token)
  3302. X`009(prsmatch (or (get token 'match) token)
  3303. X`009`009  stream)))
  3304. X
  3305. X(defun prsnary (token stream)
  3306. X  (defun loop (l)
  3307. X    (if (eq? token (peek-token stream))
  3308. X`009(begin (read-token stream)
  3309. X`009       (loop (cons (parse (rbp token) stream) l)))
  3310. X      (reverse l)))
  3311. X  (loop (list (parse (rbp token) stream))))
  3312. X
  3313. X(defun prsmatch (token stream)
  3314. X  (if (eq? token (peek-token stream))
  3315. X      (begin (read-token stream)
  3316. X`009     nil)
  3317. X    (begin (defun loop (l)
  3318. X`009     (if (eq? token (peek-token stream))
  3319. X`009`009 (begin (read-token stream)
  3320. X`009`009`009(reverse l))
  3321. X`009       (if (eq? 'COMMA (peek-token stream))
  3322. X`009`009   (begin (read-token stream)
  3323. X`009`009`009  (loop (cons (parse 10 stream) l)))
  3324. X`009`009 (error 'comma-or-match-not-found (read-token stream)))))
  3325. X`009   (loop (list (parse 10 stream))))))
  3326. X
  3327. X(defun delim-err (token stream)
  3328. X  (error 'illegal-use-of-delimiter token))
  3329. X
  3330. X(defun erb-error (token left stream)
  3331. X  (error 'too-many token))
  3332. X
  3333. X(defun premterm-err (token stream)
  3334. X  (error 'premature-termination-of-input token))
  3335. X
  3336. X(defmac (defprops form)
  3337. X  (defun loop (l result)
  3338. X    (if (null? l)
  3339. X`009`096(begin ,@result)
  3340. X      (loop (cddr l)
  3341. X`009    `096((putprop ',(cadr form) ',(cadr l) ',(car l))
  3342. X`009      ,@result))))
  3343. X  (loop (cddr form) nil))
  3344. X
  3345. X
  3346. X(defprops $
  3347. X  lbp -1
  3348. X  nud premterm-err)
  3349. X
  3350. X(defprops COMMA
  3351. X  lbp 10
  3352. X  nud delim-err)
  3353. X
  3354. X
  3355. X(defprops ]
  3356. X  nud delim-err
  3357. X  led erb-err
  3358. X  lbp 5)
  3359. X
  3360. X(defprops [
  3361. X  nud open-paren-nud
  3362. X  led open-paren-led
  3363. X  lbp 200)
  3364. X
  3365. X(defprops if
  3366. X  nud if-nud
  3367. X  rbp 45)
  3368. X
  3369. X(defprops then
  3370. X  nud delim-err
  3371. X  lbp 5
  3372. X  rbp 25)
  3373. X
  3374. X(defprops else
  3375. X  nud delim-err
  3376. X  lbp 5
  3377. X  rbp 25)
  3378. X
  3379. X(defprops -
  3380. X  nud parse-prefix
  3381. X  led parse-nary
  3382. X  lbp 100
  3383. X  rbp 100)
  3384. X
  3385. X(defprops +
  3386. X  nud parse-prefix
  3387. X  led parse-nary
  3388. X  lbp 100
  3389. X  rbp 100)
  3390. X
  3391. X(defprops *
  3392. X  led parse-nary
  3393. X  lbp 120)
  3394. X
  3395. X(defprops =
  3396. X  led parse-infix
  3397. X  lbp 80
  3398. X  rbp 80)
  3399. X
  3400. X(defprops **
  3401. X  lbp 140
  3402. X  rbp 139
  3403. X  led parse-infix)
  3404. X
  3405. X(defprops :=
  3406. X  led parse-infix
  3407. X  lbp 80
  3408. X  rbp 80)
  3409. X
  3410. X
  3411. X(defprops /
  3412. X  led parse-infix
  3413. X  lbp 120
  3414. X  rbp 120)
  3415. X
  3416. X(defprops >
  3417. X  led parse-infix
  3418. X  lbp 80
  3419. X  rbp 80)
  3420. X
  3421. X(defprops <
  3422. X  led parse-infix
  3423. X  lbp 80
  3424. X  rbp 80)
  3425. X
  3426. X(defprops >=
  3427. X  led parse-infix
  3428. X  lbp 80
  3429. X  rbp 80)
  3430. X
  3431. X(defprops <=
  3432. X  led parse-infix
  3433. X  lbp 80
  3434. X  rbp 80)
  3435. X
  3436. X(defprops not
  3437. X  nud parse-prefix
  3438. X  lbp 70
  3439. X  rbp 70)
  3440. X
  3441. X(defprops and
  3442. X  led parse-nary
  3443. X  lbp 65)
  3444. X
  3445. X(defprops or
  3446. X  led parse-nary
  3447. X  lbp 60)
  3448. X
  3449. X
  3450. X(defun open-paren-nud (token stream)
  3451. X  (if (eq (peek-token stream) '])
  3452. X      nil
  3453. X    (let ((right (prsmatch '] stream)))
  3454. X      (if (cdr right)
  3455. X`009  (cons 'sequence right)
  3456. X`009(car right)))))
  3457. X
  3458. X(defun open-paren-led (token left stream)
  3459. X  (cons (header left) (prsmatch '] stream)))
  3460. X
  3461. X
  3462. X(defun if-nud (token stream)
  3463. X  (define pred (parse (rbp token) stream))
  3464. X  (define then (if (eq? (peek-token stream) 'then)
  3465. X`009`009   (parse (rbp (read-token stream)) stream)
  3466. X`009`009 (error 'missing-then)))
  3467. X  (if (eq? (peek-token stream) 'else)
  3468. X      `096(if ,pred ,then ,(parse (rbp (read-token stream)) stream))
  3469. X    `096(if ,pred ,then)))
  3470. $ GOSUB UNPACK_FILE
  3471.  
  3472. $ FILE_IS = "DESCRIP.MMS"
  3473. $ CHECKSUM_IS = 1126381153
  3474. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3475. X! VMS MAKEFILE (using MMS)
  3476. X!
  3477. X
  3478. XCFLAGS = /DEBUG/LIST/SHOW=(NOSOURCE)/OPTIMIZE=(NOINLINE)/STANDARD=PORTABLE
  3479. X
  3480. XOBJS = siod.obj,slib.obj,sliba.obj
  3481. X
  3482. Xsiod.exe depends_on $(OBJS),siod.opt
  3483. X dflag = ""
  3484. X if f$type(setdebug) .nes. "" then dflag = "/DEBUG"
  3485. X link'dflag'/exe=siod.exe $(OBJS),siod.opt/opt
  3486. X if f$type(setdebug) .nes. "" then setdebug siod.exe 0
  3487. X ! re-execute the next line in your superior process:
  3488. X siod == "$" + f$env("DEFAULT") + "SIOD"
  3489. X
  3490. XDISTRIB depends_on siod.shar,siod.1_of_1
  3491. X !(ALL DONE)
  3492. X
  3493. Xsiod.obj depends_on siod.c,siod.h,
  3494. X
  3495. Xslib.obj depends_on slib.c,siod.h,siodp.h
  3496. Xsliba,obj depends_on sliba.c,siod.h,siodp.h
  3497. X
  3498. XDISTRIB_FILES = MAKEFILE.,README.,SIOD.1,SIOD.C,SIOD.DOC,SIOD.H,SIOD.SCM,\
  3499. X                SLIB.C,SIOD.TIM,MAKEFILE.COM,PRATT.SCM,DESCRIP.MMS,SIOD.OPT,\
  3500. X                SHAR.DB,SIODP.H,SLIBA.C,SIODM.C
  3501. X
  3502. Xsiod.shar depends_on $(DISTRIB_FILES)
  3503. X minishar siod.shar shar.db
  3504. X
  3505. XSIOD.1_OF_1  depends_on $(DISTRIB_FILES)
  3506. X DEFINE share_max_part_size 300
  3507. X @NTOOLS_DIR:VMS_SHARE "$(DISTRIB_FILES)" SIOD
  3508. $ GOSUB UNPACK_FILE
  3509.  
  3510. $ FILE_IS = "SIOD.OPT"
  3511. $ CHECKSUM_IS = 1511619186
  3512. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3513. XIDENTIFICATION = "SIOD 2.6"
  3514. Xsys$library:vaxcrtl/share
  3515. $ GOSUB UNPACK_FILE
  3516.  
  3517. $ FILE_IS = "SHAR.DB"
  3518. $ CHECKSUM_IS = 2132950022
  3519. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3520. Xreadme
  3521. X! the source
  3522. Xsiod.h
  3523. Xsiodp.h
  3524. Xsiod.c
  3525. Xslib.c
  3526. Xsliba.c
  3527. Xsiodm.c
  3528. X! documentation
  3529. Xsiod.doc
  3530. Xsiod.tim
  3531. X! lisp code
  3532. Xpratt.scm
  3533. Xsiod.scm
  3534. X! unix-specific
  3535. Xmakefile
  3536. Xsiod.1
  3537. X! vms-specific
  3538. Xmakefile.com
  3539. Xdescrip.mms
  3540. Xsiod.opt
  3541. X! this file:
  3542. Xshar.db
  3543. $ GOSUB UNPACK_FILE
  3544.  
  3545. $ FILE_IS = "SIODP.H"
  3546. $ CHECKSUM_IS = 1028115566
  3547. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3548. X/* Scheme In One Defun, but in C this time.
  3549. X
  3550. X *                        COPYRIGHT (c) 1988-1992 BY                        *
  3551. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  3552. X *        See the source file SLIB.C for more information.                  *
  3553. X
  3554. XDeclarations which are private to SLIB.C internals.
  3555. X
  3556. X*/
  3557. X
  3558. X
  3559. Xextern char *tkbuffer;
  3560. Xextern LISP heap,heap_end,heap_org;
  3561. Xextern LISP truth;
  3562. X
  3563. Xstruct user_type_hooks
  3564. X`123LISP (*gc_relocate)(LISP);
  3565. X void (*gc_scan)(LISP);
  3566. X LISP (*gc_mark)(LISP);
  3567. X void (*gc_free)(LISP);
  3568. X void (*prin1)(LISP, FILE *);
  3569. X LISP (*leval)(LISP, LISP *, LISP *);
  3570. X long (*c_sxhash)(LISP,long);
  3571. X LISP (*fast_print)(LISP,LISP);
  3572. X LISP (*fast_read)(int,LISP);
  3573. X LISP (*equal)(LISP,LISP);`125;
  3574. X
  3575. Xstruct catch_frame
  3576. X`123LISP tag;
  3577. X LISP retval;
  3578. X jmp_buf cframe;
  3579. X struct catch_frame *next;`125;
  3580. X
  3581. Xstruct gc_protected
  3582. X`123LISP *location;
  3583. X long length;
  3584. X struct gc_protected *next;`125;
  3585. X
  3586. X#define NEWCELL(_into,_type)          \
  3587. X`123if (gc_kind_copying == 1)            \
  3588. X   `123if ((_into = heap) >= heap_end)   \
  3589. X      gc_fatal_error();               \
  3590. X    heap = _into+1;`125                  \
  3591. X else                                 \
  3592. X   `123if NULLP(freelist)                \
  3593. X      gc_for_newcell();               \
  3594. X    _into = freelist;                 \
  3595. X    freelist = CDR(freelist);         \
  3596. X    ++gc_cells_allocated;`125            \
  3597. X (*_into).gc_mark = 0;                \
  3598. X (*_into).type = _type;`125
  3599. X
  3600. X#ifdef THINK_C
  3601. Xextern int ipoll_counter;
  3602. Xvoid full_interrupt_poll(int *counter);
  3603. V#define INTERRUPT_CHECK() if (--ipoll_counter < 0) full_interrupt_poll(&ipoll
  3604. X_counter)
  3605. X#else
  3606. X#define INTERRUPT_CHECK()
  3607. X#endif
  3608. X
  3609. Xextern char *stack_limit_ptr;
  3610. X
  3611. X#define STACK_LIMIT(_ptr,_amt) (((char *)_ptr) - (_amt))
  3612. X
  3613. X#define STACK_CHECK(_ptr) \
  3614. X  if (((char *) (_ptr)) < stack_limit_ptr) err_stack((char *) _ptr);
  3615. X
  3616. Xvoid err_stack(char *);
  3617. X
  3618. X#ifdef VMS
  3619. X#define SIG_restargs ,...
  3620. X#else
  3621. X#define SIG_restargs
  3622. X#endif
  3623. X
  3624. Xvoid handle_sigfpe(int sig SIG_restargs);
  3625. Xvoid handle_sigint(int sig SIG_restargs);
  3626. Xvoid err_ctrl_c(void);
  3627. Xdouble myruntime(void);
  3628. Xvoid fput_st(FILE *f,char *st);
  3629. Xvoid put_st(char *st);
  3630. Xvoid grepl_puts(char *st);
  3631. Xvoid gc_fatal_error(void);
  3632. Xchar *must_malloc(unsigned long size);
  3633. XLISP gen_intern(char *name,long copyp);
  3634. Xvoid scan_registers(void);
  3635. Xvoid init_storage_1(void);
  3636. Xstruct user_type_hooks *get_user_type_hooks(long type);
  3637. XLISP get_newspace(void);
  3638. Xvoid scan_newspace(LISP newspace);
  3639. Xvoid free_oldspace(LISP space,LISP end);
  3640. Xvoid gc_stop_and_copy(void);
  3641. Xvoid gc_for_newcell(void);
  3642. Xvoid gc_mark_and_sweep(void);
  3643. Xvoid gc_ms_stats_start(void);
  3644. Xvoid gc_ms_stats_end(void);
  3645. Xvoid gc_mark(LISP ptr);
  3646. Xvoid mark_protected_registers(void);
  3647. Xvoid mark_locations(LISP *start,LISP *end);
  3648. Xvoid mark_locations_array(LISP *x,long n);
  3649. Xvoid gc_sweep(void);
  3650. XLISP leval_args(LISP l,LISP env);
  3651. XLISP extend_env(LISP actuals,LISP formals,LISP env);
  3652. XLISP envlookup(LISP var,LISP env);
  3653. XLISP setvar(LISP var,LISP val,LISP env);
  3654. XLISP leval_setq(LISP args,LISP env);
  3655. XLISP syntax_define(LISP args);
  3656. XLISP leval_define(LISP args,LISP env);
  3657. XLISP leval_if(LISP *pform,LISP *penv);
  3658. XLISP leval_lambda(LISP args,LISP env);
  3659. XLISP leval_progn(LISP *pform,LISP *penv);
  3660. XLISP leval_or(LISP *pform,LISP *penv);
  3661. XLISP leval_and(LISP *pform,LISP *penv);
  3662. XLISP leval_catch(LISP args,LISP env);
  3663. XLISP lthrow(LISP tag,LISP value);
  3664. XLISP leval_let(LISP *pform,LISP *penv);
  3665. XLISP reverse(LISP l);
  3666. XLISP let_macro(LISP form);
  3667. XLISP leval_quote(LISP args,LISP env);
  3668. XLISP leval_tenv(LISP args,LISP env);
  3669. Xint flush_ws(struct gen_readio *f,char *eoferr);
  3670. Xint f_getc(FILE *f);
  3671. Xvoid f_ungetc(int c, FILE *f);
  3672. XLISP readtl(struct gen_readio *f);
  3673. XLISP lreadr(struct gen_readio *f);
  3674. XLISP lreadparen(struct gen_readio *f);
  3675. Xvoid close_open_files(void);
  3676. XLISP arglchk(LISP x);
  3677. Xvoid init_storage_a1(long type);
  3678. Xvoid init_storage_a(void);
  3679. XLISP array_gc_relocate(LISP ptr);
  3680. Xvoid array_gc_scan(LISP ptr);
  3681. XLISP array_gc_mark(LISP ptr);
  3682. Xvoid array_gc_free(LISP ptr);
  3683. Xvoid array_prin1(LISP ptr,FILE *f);
  3684. Xlong array_sxhaxh(LISP,long);
  3685. XLISP array_fast_print(LISP,LISP);
  3686. XLISP array_fast_read(int,LISP);
  3687. XLISP array_equal(LISP,LISP);
  3688. Xlong array_sxhash(LISP,long);
  3689. X
  3690. Xint rfs_getc(unsigned char **p);
  3691. Xvoid rfs_ungetc(unsigned char c,unsigned char **p);
  3692. Xvoid err1_aset1(LISP i);
  3693. Xvoid err2_aset1(LISP v);
  3694. XLISP lreadstring(struct gen_readio *f);
  3695. X
  3696. Xvoid file_gc_free(LISP ptr);
  3697. Xvoid file_prin1(LISP ptr,FILE *f);
  3698. XLISP fopen_c(char *name,char *how);
  3699. XLISP fopen_l(LISP name,LISP how);
  3700. XLISP fclose_l(LISP p);
  3701. XFILE *get_c_file(LISP p,FILE *deflt);
  3702. XLISP lgetc(LISP p);
  3703. XLISP lputc(LISP c,LISP p);
  3704. XLISP lputs(LISP str,LISP p);
  3705. X
  3706. XLISP leval_while(LISP args,LISP env);
  3707. X
  3708. Xvoid init_subrs_a(void);
  3709. Xvoid init_subrs_1(void);
  3710. X
  3711. Xlong href_index(LISP table,LISP key);
  3712. X
  3713. Xvoid put_long(long,FILE *);
  3714. Xlong get_long(FILE *);
  3715. X
  3716. Xlong fast_print_table(LISP obj,LISP table);
  3717. X
  3718. XLISP stack_limit(LISP,LISP);
  3719. X
  3720. X
  3721. Xvoid err0(void);
  3722. Xvoid pr(LISP);
  3723. Xvoid prp(LISP *);
  3724. X
  3725. $ GOSUB UNPACK_FILE
  3726.  
  3727. $ FILE_IS = "SLIBA.C"
  3728. $ CHECKSUM_IS = 1296885096
  3729. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  3730. X/* `032
  3731. X *                   COPYRIGHT (c) 1988-1992 BY                             *
  3732. X *        PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS.       *
  3733. X *        See the source file SLIB.C for more information.                  *
  3734. X
  3735. XArray-hacking code moved to another source file.
  3736. X
  3737. X*/
  3738. X
  3739. X#include <stdio.h>
  3740. X#include <string.h>
  3741. X#include <setjmp.h>
  3742. X#include <stdlib.h>
  3743. X#include <ctype.h>
  3744. X
  3745. X#include "siod.h"
  3746. X#include "siodp.h"
  3747. X
  3748. XLISP bashnum = NIL;
  3749. X
  3750. Xvoid init_storage_a1(long type)
  3751. X`123long j;
  3752. X struct user_type_hooks *p;
  3753. X set_gc_hooks(type,
  3754. X`009      array_gc_relocate,
  3755. X`009      array_gc_mark,
  3756. X`009      array_gc_scan,
  3757. X`009      array_gc_free,
  3758. X`009      &j);
  3759. X set_print_hooks(type,array_prin1);
  3760. X p = get_user_type_hooks(type);
  3761. X p->fast_print = array_fast_print;
  3762. X p->fast_read = array_fast_read;
  3763. X p->equal = array_equal;
  3764. X p->c_sxhash = array_sxhash;`125
  3765. X
  3766. Xvoid init_storage_a(void)
  3767. X`123long j;
  3768. X gc_protect(&bashnum);
  3769. X bashnum = newcell(tc_flonum);
  3770. X init_storage_a1(tc_string);
  3771. X init_storage_a1(tc_double_array);
  3772. X init_storage_a1(tc_long_array);
  3773. X init_storage_a1(tc_lisp_array);`125
  3774. X
  3775. XLISP array_gc_relocate(LISP ptr)
  3776. X`123LISP new;
  3777. X if ((new = heap) >= heap_end) gc_fatal_error();
  3778. X heap = new+1;
  3779. X memcpy(new,ptr,sizeof(struct obj));
  3780. X return(new);`125
  3781. X
  3782. Xvoid array_gc_scan(LISP ptr)
  3783. X`123long j;
  3784. X if TYPEP(ptr,tc_lisp_array)
  3785. X   for(j=0;j < ptr->storage_as.lisp_array.dim; ++j)
  3786. X     ptr->storage_as.lisp_array.data[j] =    `032
  3787. X       gc_relocate(ptr->storage_as.lisp_array.data[j]);`125
  3788. X
  3789. XLISP array_gc_mark(LISP ptr)
  3790. X`123long j;
  3791. X if TYPEP(ptr,tc_lisp_array)
  3792. X   for(j=0;j < ptr->storage_as.lisp_array.dim; ++j)
  3793. X     gc_mark(ptr->storage_as.lisp_array.data[j]);
  3794. X return(NIL);`125
  3795. X
  3796. Xvoid array_gc_free(LISP ptr)
  3797. X`123switch (ptr->type)
  3798. X   `123case tc_string:
  3799. X      free(ptr->storage_as.string.data);
  3800. X      break;
  3801. X    case tc_double_array:
  3802. X      free(ptr->storage_as.double_array.data);
  3803. X      break;
  3804. X    case tc_long_array:
  3805. X      free(ptr->storage_as.long_array.data);
  3806. X      break;
  3807. X    case tc_lisp_array:
  3808. X      free(ptr->storage_as.lisp_array.data);
  3809. X      break;`125`125
  3810. X
  3811. Xvoid array_prin1(LISP ptr,FILE *f)
  3812. X`123int j;
  3813. X switch (ptr->type)
  3814. X   `123case tc_string:
  3815. X      fput_st(f,"\"");
  3816. X      fput_st(f,ptr->storage_as.string.data);
  3817. X      fput_st(f,"\"");
  3818. X      break;
  3819. X    case tc_double_array:
  3820. X      fput_st(f,"#(");
  3821. X      for(j=0; j < ptr->storage_as.double_array.dim; ++j)
  3822. X`009`123sprintf(tkbuffer,"%g",ptr->storage_as.double_array.data[j]);
  3823. X`009 fput_st(f,tkbuffer);
  3824. X`009 if ((j + 1) < ptr->storage_as.double_array.dim)
  3825. X`009   fput_st(f," ");`125
  3826. X      fput_st(f,")");
  3827. X      break;
  3828. X    case tc_long_array:
  3829. X      fput_st(f,"#(");
  3830. X      for(j=0; j < ptr->storage_as.long_array.dim; ++j)
  3831. X`009`123sprintf(tkbuffer,"%ld",ptr->storage_as.long_array.data[j]);
  3832. X`009 fput_st(f,tkbuffer);
  3833. X`009 if ((j + 1) < ptr->storage_as.long_array.dim)
  3834. X`009   fput_st(f," ");`125
  3835. X      fput_st(f,")");
  3836. X      break;
  3837. X    case tc_lisp_array:
  3838. X      fput_st(f,"#(");
  3839. X      for(j=0; j < ptr->storage_as.lisp_array.dim; ++j)
  3840. X`009`123lprin1f(ptr->storage_as.lisp_array.data[j],f);
  3841. X`009 if ((j + 1) < ptr->storage_as.lisp_array.dim)
  3842. X`009   fput_st(f," ");`125
  3843. X      fput_st(f,")");
  3844. X      break;`125`125
  3845. X
  3846. XLISP strcons(long length,char *data)
  3847. X`123long flag;
  3848. X LISP s;
  3849. X flag = no_interrupt(1);
  3850. X s = cons(NIL,NIL);
  3851. X s->type = tc_string;
  3852. X s->storage_as.string.data = must_malloc(length+1);
  3853. X s->storage_as.string.dim = length;
  3854. X if (data)
  3855. X   strcpy(s->storage_as.string.data,data);
  3856. X no_interrupt(flag);
  3857. X return(s);`125
  3858. X
  3859. Xint rfs_getc(unsigned char **p)
  3860. X`123int i;
  3861. X i = **p;
  3862. X if (!i) return(EOF);
  3863. X *p = *p + 1;
  3864. X return(i);`125
  3865. X
  3866. Xvoid rfs_ungetc(unsigned char c,unsigned char **p)
  3867. X`123*p = *p - 1;`125
  3868. X
  3869. XLISP read_from_string(LISP x)
  3870. X`123char *p;
  3871. X struct gen_readio s;
  3872. X p = get_c_string(x);
  3873. X s.getc_fcn = (int (*)(char *))rfs_getc;
  3874. X s.ungetc_fcn = (void (*)(int, char *))rfs_ungetc;
  3875. X s.cb_argument = (char *) &p;
  3876. X return(readtl(&s));`125
  3877. X
  3878. XLISP aref1(LISP a,LISP i)
  3879. X`123long k;
  3880. X if NFLONUMP(i) err("bad index to aref",i);
  3881. X k = FLONM(i);
  3882. X if (k < 0) err("negative index to aref",i);
  3883. X switch (a->type)
  3884. X   `123case tc_string:
  3885. X      if (k >= (a->storage_as.string.dim - 1)) err("index too large",i);
  3886. X      return(flocons((double) a->storage_as.string.data[k]));
  3887. X    case tc_double_array:
  3888. X      if (k >= a->storage_as.double_array.dim) err("index too large",i);
  3889. X      return(flocons(a->storage_as.double_array.data[k]));
  3890. X    case tc_long_array:
  3891. X      if (k >= a->storage_as.long_array.dim) err("index too large",i);
  3892. X      return(flocons(a->storage_as.long_array.data[k]));
  3893. X    case tc_lisp_array:
  3894. X      if (k >= a->storage_as.lisp_array.dim) err("index too large",i);
  3895. X      return(a->storage_as.lisp_array.data[k]);
  3896. X    default:
  3897. X      err("invalid argument to aref",a);`125`125
  3898. X
  3899. Xvoid err1_aset1(LISP i)
  3900. X`123err("index to aset too large",i);`125
  3901. X
  3902. Xvoid err2_aset1(LISP v)
  3903. X`123err("bad value to store in array",v);`125
  3904. X
  3905. XLISP aset1(LISP a,LISP i,LISP v)
  3906. X`123long k;
  3907. X if NFLONUMP(i) err("bad index to aset",i);
  3908. X k = FLONM(i);
  3909. X if (k < 0) err("negative index to aset",i);
  3910. X switch (a->type)
  3911. X   `123case tc_string:
  3912. X      if NFLONUMP(v) err2_aset1(v);
  3913. X      if (k >= (a->storage_as.string.dim - 1)) err1_aset1(i);
  3914. X      a->storage_as.string.data[k] = (char) FLONM(v);
  3915. X      return(v);
  3916. X    case tc_double_array:
  3917. X      if NFLONUMP(v) err2_aset1(v);
  3918. X      if (k >= a->storage_as.double_array.dim) err1_aset1(i);
  3919. X      a->storage_as.double_array.data[k] = FLONM(v);
  3920. X      return(v);
  3921. X    case tc_long_array:
  3922. X      if NFLONUMP(v) err2_aset1(v);
  3923. X      if (k >= a->storage_as.long_array.dim) err1_aset1(i);
  3924. X      a->storage_as.long_array.data[k] = (long) FLONM(v);
  3925. X      return(v);
  3926. X    case tc_lisp_array:
  3927. X      if (k >= a->storage_as.lisp_array.dim) err1_aset1(i);
  3928. X      a->storage_as.lisp_array.data[k] = v;
  3929. X      return(v);
  3930. X    default:
  3931. X      err("invalid argument to aset",a);`125`125
  3932. X
  3933. XLISP cons_array(LISP dim,LISP kind)
  3934. X`123LISP a;
  3935. X long flag,n,j;
  3936. X if (NFLONUMP(dim) `124`124 (FLONM(dim) < 0))
  3937. X   err("bad dimension to cons-array",dim);
  3938. X else
  3939. X   n = FLONM(dim);
  3940. X flag = no_interrupt(1);
  3941. X a = cons(NIL,NIL);
  3942. X if EQ(cintern("double"),kind)
  3943. X   `123a->type = tc_double_array;
  3944. X    a->storage_as.double_array.dim = n;
  3945. X    a->storage_as.double_array.data = (double *) must_malloc(n *
  3946. X`009`009`009`009`009`009`009     sizeof(double));
  3947. X    for(j=0;j<n;++j) a->storage_as.double_array.data[j] = 0.0;`125
  3948. X else if EQ(cintern("long"),kind)
  3949. X   `123a->type = tc_long_array;
  3950. X    a->storage_as.long_array.dim = n;
  3951. X    a->storage_as.long_array.data = (long *) must_malloc(n * sizeof(long));
  3952. X    for(j=0;j<n;++j) a->storage_as.long_array.data[j] = 0;`125
  3953. X else if EQ(cintern("string"),kind)
  3954. X   `123a->type = tc_string;
  3955. X    a->storage_as.double_array.dim = n+1;
  3956. X    a->storage_as.string.data = (char *) must_malloc(n+1);
  3957. X    a->storage_as.string.data[n] = 0;
  3958. X    for(j=0;j<n;++j) a->storage_as.string.data[j] = ' ';`125
  3959. X else if (EQ(cintern("lisp"),kind) `124`124 NULLP(kind))
  3960. X   `123a->type = tc_lisp_array;
  3961. X    a->storage_as.lisp_array.dim = n;
  3962. X    a->storage_as.lisp_array.data = (LISP *) must_malloc(n * sizeof(LISP));
  3963. X    for(j=0;j<n;++j) a->storage_as.lisp_array.data[j] = NIL;`125
  3964. X else
  3965. X   err("bad type of array",kind);
  3966. X no_interrupt(flag);
  3967. X return(a);`125
  3968. X
  3969. XLISP string_append(LISP args)
  3970. X`123long size;
  3971. X LISP l,s;
  3972. X char *data;
  3973. X size = 0;
  3974. X for(l=args;NNULLP(l);l=cdr(l))
  3975. X   size += strlen(get_c_string(car(l)));
  3976. X s = strcons(size,NULL);
  3977. X data = s->storage_as.string.data;
  3978. X data[0] = 0;
  3979. X for(l=args;NNULLP(l);l=cdr(l))
  3980. X   strcat(data,get_c_string(car(l)));
  3981. X return(s);`125
  3982. X
  3983. XLISP lreadstring(struct gen_readio *f)
  3984. X`123int j,c,n;
  3985. X char *p;
  3986. X j = 0;
  3987. X p = tkbuffer;
  3988. X while(((c = GETC_FCN(f)) != '"') && (c != EOF))
  3989. X   `123if (c == '\\')
  3990. X      `123c = GETC_FCN(f);
  3991. X       if (c == EOF) err("eof after \\",NIL);
  3992. X       switch(c)
  3993. X`009 `123case 'n':
  3994. X`009    c = '\n';
  3995. X`009    break;
  3996. X`009  case 't':
  3997. X`009    c = '\t';
  3998. X`009    break;
  3999. X`009  case 'r':
  4000. X`009    c = '\r';
  4001. X`009    break;
  4002. X`009  case 'd':
  4003. X`009    c = 0x04;
  4004. X`009    break;
  4005. X`009  case 'N':
  4006. X`009    c = 0;
  4007. X`009    break;
  4008. X`009  case 's':
  4009. X`009    c = ' ';
  4010. X`009    break;
  4011. X`009  case '0':
  4012. X`009    n = 0;
  4013. X`009    while(1)
  4014. X`009      `123c = GETC_FCN(f);
  4015. X`009       if (c == EOF) err("eof after \\0",NIL);
  4016. X`009       if (isdigit(c))
  4017. X`009`009 n = n * 8 + c - '0';
  4018. X`009       else
  4019. X`009`009 `123UNGETC_FCN(c,f);
  4020. X`009`009  break;`125`125
  4021. X`009    c = n;`125`125
  4022. X    if ((j + 1) >= TKBUFFERN) err("read string overflow",NIL);
  4023. X    ++j;
  4024. X    *p++ = c;`125
  4025. X *p = 0;
  4026. X return(strcons(j,tkbuffer));`125
  4027. X
  4028. X#define HASH_COMBINE(_h1,_h2,_mod) (((_h1 * 17) `094 _h2) % _mod)
  4029. X
  4030. Xlong c_sxhash(LISP obj,long n)
  4031. X`123long hash,c;
  4032. X unsigned char *s;
  4033. X LISP tmp;
  4034. X struct user_type_hooks *p;
  4035. X STACK_CHECK(&obj);
  4036. X INTERRUPT_CHECK();
  4037. X switch TYPE(obj)
  4038. X   `123case tc_nil:
  4039. X      return(0);
  4040. X    case tc_cons:
  4041. X      hash = c_sxhash(car(obj),n);
  4042. X      for(tmp=cdr(obj);CONSP(tmp);tmp=cdr(tmp))
  4043. X`009hash = HASH_COMBINE(hash,c_sxhash(car(tmp),n),n);
  4044. X      hash = HASH_COMBINE(hash,c_sxhash(cdr(tmp),n),n);
  4045. X      return(hash);
  4046. X    case tc_symbol:
  4047. X      for(hash=0,s=(unsigned char *)PNAME(obj);*s;++s)
  4048. X`009hash = HASH_COMBINE(hash,*s,n);
  4049. X      return(hash);
  4050. X    case tc_subr_0:
  4051. X    case tc_subr_1:
  4052. X    case tc_subr_2:
  4053. X    case tc_subr_3:
  4054. X    case tc_lsubr:
  4055. X    case tc_fsubr:
  4056. X    case tc_msubr:
  4057. X      for(hash=0,s=(unsigned char *) obj->storage_as.subr.name;*s;++s)
  4058. X`009hash = HASH_COMBINE(hash,*s,n);
  4059. X      return(hash);
  4060. X    case tc_flonum:
  4061. X      return(((unsigned long)FLONM(obj)) % n);
  4062. X    default:
  4063. X      p = get_user_type_hooks(TYPE(obj));
  4064. X      if (p->c_sxhash)
  4065. X`009return((*p->c_sxhash)(obj,n));
  4066. X      else
  4067. X`009return(0);`125`125
  4068. X
  4069. XLISP sxhash(LISP obj,LISP n)
  4070. X`123return(flocons(c_sxhash(obj,FLONUMP(n) ? FLONM(n) : 10000)));`125
  4071. X
  4072. XLISP equal(LISP a,LISP b)
  4073. X`123struct user_type_hooks *p;
  4074. X long atype;
  4075. X STACK_CHECK(&a);
  4076. X loop:
  4077. X INTERRUPT_CHECK();
  4078. X if EQ(a,b) return(truth);
  4079. X atype = TYPE(a);
  4080. X if (atype != TYPE(b)) return(NIL);
  4081. X switch(atype)
  4082. X   `123case tc_cons:
  4083. X      if NULLP(equal(car(a),car(b))) return(NIL);
  4084. X      a = cdr(a);
  4085. X      b = cdr(b);
  4086. X      goto loop;
  4087. X    case tc_flonum:
  4088. X      return((FLONM(a) == FLONM(b)) ? truth : NIL);
  4089. X    case tc_symbol:
  4090. X      return(NIL);
  4091. X    default:
  4092. X      p = get_user_type_hooks(atype);
  4093. X      if (p->equal)
  4094. X`009return((*p->equal)(a,b));
  4095. X      else
  4096. X`009return(NIL);`125`125
  4097. X
  4098. XLISP array_equal(LISP a,LISP b)
  4099. X`123long j,len;
  4100. X switch(TYPE(a))
  4101. X   `123case tc_string:
  4102. X      len = a->storage_as.string.dim;
  4103. X      if (len != b->storage_as.string.dim) return(NIL);
  4104. V      if (memcmp(a->storage_as.string.data,b->storage_as.string.data,len) ==
  4105. X 0)
  4106. X`009return(truth);
  4107. X      else
  4108. X`009return(NIL);
  4109. X    case tc_long_array:
  4110. X      len = a->storage_as.long_array.dim;
  4111. X      if (len != b->storage_as.long_array.dim) return(NIL);
  4112. X      if (memcmp(a->storage_as.long_array.data,
  4113. X`009`009 b->storage_as.long_array.data,
  4114. X`009`009 len * sizeof(long)) == 0)
  4115. X`009return(truth);
  4116. X      else
  4117. X`009return(NIL);
  4118. X    case tc_double_array:
  4119. X      len = a->storage_as.double_array.dim;
  4120. X      if (len != b->storage_as.double_array.dim) return(NIL);
  4121. X      for(j=0;j<len;++j)
  4122. X`009if (a->storage_as.double_array.data[j] !=
  4123. X`009    b->storage_as.double_array.data[j])
  4124. X`009  return(NIL);
  4125. X      return(truth);
  4126. X    case tc_lisp_array:
  4127. X      len = a->storage_as.lisp_array.dim;
  4128. X      if (len != b->storage_as.lisp_array.dim) return(NIL);
  4129. X      for(j=0;j<len;++j)
  4130. X`009if NULLP(equal(a->storage_as.lisp_array.data[j],
  4131. X`009`009       b->storage_as.lisp_array.data[j]))
  4132. X`009  return(NIL);
  4133. X      return(truth);`125`125
  4134. X
  4135. Xlong array_sxhash(LISP a,long n)
  4136. X`123long j,len,hash;
  4137. X unsigned char *char_data;
  4138. X unsigned long *long_data;
  4139. X double *double_data;
  4140. X switch(TYPE(a))
  4141. X   `123case tc_string:
  4142. X      len = a->storage_as.string.dim;
  4143. X      for(j=0,hash=0,char_data=(unsigned char *)a->storage_as.string.data;
  4144. X`009  j < len;
  4145. X`009  ++j,++char_data)
  4146. X`009hash = HASH_COMBINE(hash,*char_data,n);
  4147. X      return(hash);
  4148. X    case tc_long_array:
  4149. X      len = a->storage_as.long_array.dim;
  4150. V      for(j=0,hash=0,long_data=(unsigned long *)a->storage_as.long_array.data
  4151. X;
  4152. X`009  j < len;
  4153. X`009  ++j,++long_data)
  4154. X`009hash = HASH_COMBINE(hash,*long_data % n,n);
  4155. X      return(hash);
  4156. X    case tc_double_array:
  4157. X      len = a->storage_as.double_array.dim;
  4158. X      for(j=0,hash=0,double_data=a->storage_as.double_array.data;
  4159. X`009  j < len;
  4160. X`009  ++j,++double_data)
  4161. X`009hash = HASH_COMBINE(hash,(unsigned long)*double_data % n,n);
  4162. X      return(hash);
  4163. X    case tc_lisp_array:
  4164. X      len = a->storage_as.lisp_array.dim;
  4165. X      for(j=0,hash=0; j < len; ++j)
  4166. X`009hash = HASH_COMBINE(hash,
  4167. X`009`009`009    c_sxhash(a->storage_as.lisp_array.data[j],n),
  4168. X`009`009`009    n);
  4169. X      return(hash);`125`125
  4170. X
  4171. Xlong href_index(LISP table,LISP key)
  4172. X`123long index;
  4173. X if NTYPEP(table,tc_lisp_array) err("not a hash table",table);
  4174. X index = c_sxhash(key,table->storage_as.lisp_array.dim);
  4175. X if ((index < 0) `124`124 (index >= table->storage_as.lisp_array.dim))
  4176. X   err("sxhash inconsistency",table);
  4177. X else
  4178. X   return(index);`125
  4179. X`032
  4180. XLISP href(LISP table,LISP key)
  4181. X`123return(cdr(assoc(key,
  4182. X`009`009  table->storage_as.lisp_array.data[href_index(table,key)])));`125
  4183. X
  4184. XLISP hset(LISP table,LISP key,LISP value)
  4185. X`123long index;
  4186. X LISP cell,l;
  4187. X index = href_index(table,key);
  4188. X l = table->storage_as.lisp_array.data[index];
  4189. X if NNULLP(cell = assoc(key,l))
  4190. X   return(setcdr(cell,value));
  4191. X cell = cons(key,value);
  4192. X table->storage_as.lisp_array.data[index] = cons(cell,l);
  4193. X return(value);`125
  4194. X
  4195. XLISP assoc(LISP x,LISP alist)
  4196. X`123LISP l,tmp;
  4197. X for(l=alist;CONSP(l);l=CDR(l))
  4198. X   `123tmp = CAR(l);
  4199. X    if (CONSP(tmp) && equal(CAR(tmp),x)) return(tmp);`125
  4200. X if EQ(l,NIL) return(NIL);
  4201. X err("improper list to assoc",alist);`125
  4202. X
  4203. Xvoid put_long(long i,FILE *f)
  4204. X`123fwrite(&i,sizeof(long),1,f);`125
  4205. X
  4206. Xlong get_long(FILE *f)
  4207. X`123long i;
  4208. X fread(&i,sizeof(long),1,f);
  4209. X return(i);`125
  4210. X
  4211. Xlong fast_print_table(LISP obj,LISP table)
  4212. X`123FILE *f;
  4213. X LISP ht,index;
  4214. X f = get_c_file(car(table),(FILE *) NULL);
  4215. X if NULLP(ht = car(cdr(table)))
  4216. X   return(1);
  4217. X index = href(ht,obj);
  4218. X if NNULLP(index)
  4219. X   `123putc(FO_fetch,f);
  4220. X    put_long(get_c_long(index),f);
  4221. X    return(0);`125
  4222. X if NULLP(index = car(cdr(cdr(table))))
  4223. X   return(1);
  4224. X hset(ht,obj,index);
  4225. X FLONM(bashnum) = 1.0;
  4226. X setcar(cdr(cdr(table)),plus(index,bashnum));
  4227. X putc(FO_store,f);
  4228. X put_long(get_c_long(index),f);
  4229. X return(1);`125
  4230. X
  4231. XLISP fast_print(LISP obj,LISP table)
  4232. X`123FILE *f;
  4233. X long len;
  4234. X LISP tmp;
  4235. X struct user_type_hooks *p;
  4236. X STACK_CHECK(&obj);
  4237. X f = get_c_file(car(table),(FILE *) NULL);
  4238. X switch(TYPE(obj))
  4239. X   `123case tc_nil:
  4240. X      putc(tc_nil,f);
  4241. X      return(NIL);
  4242. X    case tc_cons:
  4243. V      for(len=0,tmp=obj;CONSP(tmp);tmp=CDR(tmp)) `123INTERRUPT_CHECK();++len;
  4244. X`125
  4245. X      if (len == 1)
  4246. X`009`123putc(tc_cons,f);
  4247. X`009 fast_print(car(obj),table);
  4248. X`009 fast_print(cdr(obj),table);`125
  4249. X      else if NULLP(tmp)
  4250. X`009`123putc(FO_list,f);
  4251. X`009 put_long(len,f);
  4252. X`009 for(tmp=obj;CONSP(tmp);tmp=CDR(tmp))
  4253. X`009   fast_print(CAR(tmp),table);`125
  4254. X      else
  4255. X`009`123putc(FO_listd,f);
  4256. X`009 put_long(len,f);
  4257. X`009 for(tmp=obj;CONSP(tmp);tmp=CDR(tmp))
  4258. X`009   fast_print(CAR(tmp),table);
  4259. X`009 fast_print(tmp,table);`125
  4260. X      return(NIL);
  4261. X    case tc_flonum:
  4262. X      putc(tc_flonum,f);
  4263. X      fwrite(&obj->storage_as.flonum.data,
  4264. X`009     sizeof(obj->storage_as.flonum.data),
  4265. X`009     1,
  4266. X`009     f);
  4267. X      return(NIL);
  4268. X    case tc_symbol:
  4269. X      if (fast_print_table(obj,table))
  4270. X`009`123putc(tc_symbol,f);
  4271. X`009 len = strlen(PNAME(obj));
  4272. X`009 if (len >= TKBUFFERN)
  4273. X`009   err("symbol name too long",obj);
  4274. X`009 put_long(len,f);
  4275. X`009 fwrite(PNAME(obj),len,1,f);
  4276. X`009 return(truth);`125
  4277. X      else
  4278. X`009return(NIL);
  4279. X    default:
  4280. X      p = get_user_type_hooks(TYPE(obj));
  4281. X      if (p->fast_print)
  4282. X`009return((*p->fast_print)(obj,table));
  4283. X      else
  4284. X`009err("cannot fast-print",obj);`125`125
  4285. X
  4286. XLISP fast_read(LISP table)
  4287. X`123FILE *f;
  4288. X LISP tmp,l;
  4289. X struct user_type_hooks *p;
  4290. X int c;
  4291. X long len;
  4292. X f = get_c_file(car(table),(FILE *) NULL);
  4293. X c = getc(f);
  4294. X if (c == EOF) return(table);
  4295. X switch(c)
  4296. X   `123case FO_fetch:
  4297. X      len = get_long(f);
  4298. X      FLONM(bashnum) = len;
  4299. X      return(href(car(cdr(table)),bashnum));
  4300. X    case FO_store:
  4301. X      len = get_long(f);
  4302. X      tmp = fast_read(table);
  4303. X      hset(car(cdr(table)),flocons(len),tmp);
  4304. X      return(tmp);
  4305. X    case tc_nil:
  4306. X      return(NIL);
  4307. X    case tc_cons:
  4308. X      tmp = fast_read(table);
  4309. X      return(cons(tmp,fast_read(table)));
  4310. X    case FO_list:
  4311. X    case FO_listd:
  4312. X      len = get_long(f);
  4313. X      FLONM(bashnum) = len;
  4314. X      l = make_list(bashnum,NIL);
  4315. X      tmp = l;
  4316. X      while(len > 1)
  4317. X`009`123CAR(tmp) = fast_read(table);
  4318. X`009 tmp = CDR(tmp);
  4319. X`009 --len;`125
  4320. X      CAR(tmp) = fast_read(table);
  4321. X      if (c == FO_listd)
  4322. X`009CDR(tmp) = fast_read(table);
  4323. X      return(l);
  4324. X    case tc_flonum:
  4325. X      tmp = newcell(tc_flonum);
  4326. X      fread(&tmp->storage_as.flonum.data,
  4327. X`009    sizeof(tmp->storage_as.flonum.data),
  4328. X`009    1,
  4329. X`009    f);
  4330. X      return(tmp);
  4331. X    case tc_symbol:
  4332. X      len = get_long(f);
  4333. X      if (len >= TKBUFFERN)
  4334. X`009err("symbol name too long",NIL);
  4335. X      fread(tkbuffer,len,1,f);
  4336. X      tkbuffer[len] = 0;
  4337. X      return(rintern(tkbuffer));
  4338. X    default:
  4339. X      p = get_user_type_hooks(c);
  4340. X      if (p->fast_read)
  4341. X`009return(*p->fast_read)(c,table);
  4342. X      else
  4343. X`009err("unknown fast-read opcode",flocons(c));`125`125
  4344. X
  4345. XLISP array_fast_print(LISP ptr,LISP table)
  4346. X`123int j,len;
  4347. X FILE *f;
  4348. X f = get_c_file(car(table),(FILE *) NULL);
  4349. X switch (ptr->type)
  4350. X   `123case tc_string:
  4351. X      putc(tc_string,f);
  4352. X      len = ptr->storage_as.string.dim;
  4353. X      put_long(len,f);
  4354. X      fwrite(ptr->storage_as.string.data,len,1,f);
  4355. X      return(NIL);
  4356. X    case tc_double_array:
  4357. X      putc(tc_double_array,f);
  4358. X      len = ptr->storage_as.double_array.dim * sizeof(double);
  4359. X      put_long(len,f);
  4360. X      fwrite(ptr->storage_as.double_array.data,len,1,f);
  4361. X      return(NIL);
  4362. X    case tc_long_array:
  4363. X      putc(tc_long_array,f);
  4364. X      len = ptr->storage_as.long_array.dim * sizeof(long);
  4365. X      put_long(len,f);
  4366. X      fwrite(ptr->storage_as.long_array.data,len,1,f);
  4367. X      return(NIL);
  4368. X    case tc_lisp_array:
  4369. X      putc(tc_lisp_array,f);
  4370. X      len = ptr->storage_as.lisp_array.dim;
  4371. X      put_long(len,f);
  4372. X      for(j=0; j < len; ++j)
  4373. X`009fast_print(ptr->storage_as.lisp_array.data[j],table);
  4374. X      return(NIL);`125`125
  4375. X
  4376. XLISP array_fast_read(int code,LISP table)
  4377. X`123long j,len,iflag;
  4378. X FILE *f;
  4379. X LISP ptr;
  4380. X f = get_c_file(car(table),(FILE *) NULL);
  4381. X switch (code)
  4382. X   `123case tc_string:
  4383. X      len = get_long(f);
  4384. X      ptr = strcons(len,NULL);
  4385. X      fread(ptr->storage_as.string.data,len,1,f);
  4386. X      ptr->storage_as.string.data[len] = 0;
  4387. X      return(ptr);
  4388. X    case tc_double_array:
  4389. X      len = get_long(f);
  4390. X      iflag = no_interrupt(1);
  4391. X      ptr = newcell(tc_double_array);
  4392. X      ptr->storage_as.double_array.dim = len;
  4393. X      ptr->storage_as.double_array.data =
  4394. X`009(double *) must_malloc(len * sizeof(double));
  4395. X      fread(ptr->storage_as.double_array.data,sizeof(double),len,f);
  4396. X      no_interrupt(iflag);
  4397. X      return(ptr);
  4398. X    case tc_long_array:
  4399. X      len = get_long(f);
  4400. X      iflag = no_interrupt(1);
  4401. X      ptr = newcell(tc_long_array);
  4402. X      ptr->storage_as.long_array.dim = len;
  4403. X      ptr->storage_as.long_array.data =
  4404. X`009(long *) must_malloc(len * sizeof(long));
  4405. X      fread(ptr->storage_as.long_array.data,sizeof(long),len,f);
  4406. X      no_interrupt(iflag);
  4407. X      return(ptr);
  4408. X    case tc_lisp_array:
  4409. X      len = get_long(f);
  4410. X      FLONM(bashnum) = len;
  4411. X      ptr = cons_array(bashnum,NIL);
  4412. X      for(j=0; j < len; ++j)
  4413. X`009ptr->storage_as.lisp_array.data[j] = fast_read(table);
  4414. X      return(ptr);`125`125
  4415. X
  4416. Xlong get_c_long(LISP x)
  4417. X`123if NFLONUMP(x) err("not a number",x);
  4418. X return(FLONM(x));`125
  4419. X
  4420. XLISP make_list(LISP x,LISP v)
  4421. X`123long n;
  4422. X LISP l;
  4423. X n = get_c_long(x);
  4424. X l = NIL;
  4425. X while(n > 0)
  4426. X   `123l = cons(v,l); --n;`125
  4427. X return(l);`125
  4428. X
  4429. Xvoid init_subrs_a(void)
  4430. X`123init_subr("aref",tc_subr_2,aref1);
  4431. X init_subr("aset",tc_subr_3,aset1);
  4432. X init_subr("string-append",tc_lsubr,string_append);
  4433. X init_subr("read-from-string",tc_subr_1,read_from_string);
  4434. X init_subr("cons-array",tc_subr_2,cons_array);
  4435. X init_subr("sxhash",tc_subr_2,sxhash);
  4436. X init_subr("equal?",tc_subr_2,equal);
  4437. X init_subr("href",tc_subr_2,href);
  4438. X init_subr("hset",tc_subr_3,hset);
  4439. X init_subr("assoc",tc_subr_2,assoc);
  4440. X init_subr("fast-read",tc_subr_1,fast_read);
  4441. X init_subr("fast-print",tc_subr_2,fast_print);
  4442. X init_subr("make-list",tc_subr_2,make_list);`125
  4443. $ GOSUB UNPACK_FILE
  4444.  
  4445. $ FILE_IS = "SIODM.C"
  4446. $ CHECKSUM_IS = 604228036
  4447. $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
  4448. X/* Code specific to Lightspeed C on MacIntosh.
  4449. X   This detects that the character APPLE-DOT is depressed,
  4450. X   and then expects that sending a newline to the console
  4451. X   will invoke the proper signal handling code.`032
  4452. X
  4453. X   See the file "THINK C 5.0 FOLDER/C LIBRARIES/SOURCES/CONSOLE.C"
  4454. X
  4455. X   It would be a good thing to have some code in here that would call
  4456. X   the proper inside-mac OS routines to determine allowable machine
  4457. X   stack size, because of lack of protection against stack
  4458. X   overflow bashing another program.
  4459. X
  4460. X */
  4461. X `032
  4462. X
  4463. X#include <stdio.h>
  4464. X#include <console.h>
  4465. X
  4466. X#include <MacHeaders>
  4467. X
  4468. Xstatic int interrupt_key_down(void);
  4469. Xvoid full_interrupt_poll(int *counter);
  4470. X
  4471. Xvoid full_interrupt_poll(int *counter)
  4472. X`123SystemTask();
  4473. X if (interrupt_key_down())
  4474. X     putc('\n',stdout);
  4475. X  /* 200 seems to be a good compromise here between
  4476. X     interrupt latency and cpu-bound performance */  `032
  4477. X *counter = 200;`125
  4478. X
  4479. Xstatic int interrupt_key_down(void)
  4480. X`123EvQElPtr l;
  4481. X for(l = (EvQElPtr) EventQueue.qHead; l; l = (EvQElPtr) l->qLink)
  4482. X   if ((l->evtQWhat == keyDown) &&
  4483. X       ((char) l->evtQMessage == '.') &&
  4484. X       (l->evtQModifiers & cmdKey))
  4485. X     return(1);
  4486. X return(0);`125
  4487. $ GOSUB UNPACK_FILE
  4488. $ EXIT
  4489.  
  4490.